From 75270a426484ab8d3d2c9559745a09e6658f668a Mon Sep 17 00:00:00 2001
From: Sam Lantinga <[EMAIL REDACTED]>
Date: Tue, 2 Jun 2026 12:19:20 -0700
Subject: [PATCH] Handle java.util.ConcurrentModificationException while
unregistering sensor listeners
We're still seeing this frequently when unregistering PlayStation controller sensors. We don't know what else is modifying the sensor list, but if we end up getting this exception we'll retry after a short sleep.
---
.../java/org/libsdl/app/SDLSensorManager.java | 45 ++++++++++++++++++-
1 file changed, 43 insertions(+), 2 deletions(-)
diff --git a/android-project/app/src/main/java/org/libsdl/app/SDLSensorManager.java b/android-project/app/src/main/java/org/libsdl/app/SDLSensorManager.java
index 586e3fab6e8fd..4ed4f01278914 100644
--- a/android-project/app/src/main/java/org/libsdl/app/SDLSensorManager.java
+++ b/android-project/app/src/main/java/org/libsdl/app/SDLSensorManager.java
@@ -3,6 +3,7 @@
import android.hardware.Sensor;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
+import android.util.Log;
// This class coordinates synchronized access to sensor manager registration
//
@@ -13,6 +14,8 @@ class SDLSensorManager
{
static private SDLSensorManager mManager = new SDLSensorManager();
+ static final int RETRY_COUNT = 3;
+
public static void registerListener(SensorManager manager, SensorEventListener listener, Sensor sensor, int samplingPeriodUs) {
mManager.RegisterListener(manager, listener, sensor, samplingPeriodUs);
}
@@ -22,11 +25,49 @@ public static void unregisterListener(SensorManager manager, SensorEventListener
}
private synchronized void RegisterListener(SensorManager manager, SensorEventListener listener, Sensor sensor, int samplingPeriodUs) {
- manager.registerListener(listener, sensor, samplingPeriodUs, null);
+ int retries = 0;
+ boolean complete = false;
+ while (!complete) {
+ try {
+ manager.registerListener(listener, sensor, samplingPeriodUs, null);
+ complete = true;
+ } catch (java.util.ConcurrentModificationException e) {
+ ++retries;
+ if (retries <= RETRY_COUNT) {
+ // Sleep a bit and try again
+ try {
+ Thread.sleep(1);
+ } catch (Exception e2) {
+ }
+ } else {
+ Log.v("SDL", "Multiple ConcurrentModificationException caught while registering sensor listener, canceling operation");
+ complete = true;
+ }
+ }
+ }
}
private synchronized void UnregisterListener(SensorManager manager, SensorEventListener listener, Sensor sensor) {
- manager.unregisterListener(listener, sensor);
+ int retries = 0;
+ boolean complete = false;
+ while (!complete) {
+ try {
+ manager.unregisterListener(listener, sensor);
+ complete = true;
+ } catch (java.util.ConcurrentModificationException e) {
+ ++retries;
+ if (retries <= RETRY_COUNT) {
+ // Sleep a bit and try again
+ try {
+ Thread.sleep(1);
+ } catch (Exception e2) {
+ }
+ } else {
+ Log.v("SDL", "Multiple ConcurrentModificationException caught while unregistering sensor listener, canceling operation");
+ complete = true;
+ }
+ }
+ }
}
}