Skip to content

Commit e67d556

Browse files
javachefacebook-github-bot
authored andcommitted
Fix HeadlessJsTaskContext creating Handler on background thread (#44582)
Summary: Pull Request resolved: #44582 D54496604 fixed lifecycle methods for JavaTimerManager, which now reveals another bug. Because this codepath ends up creating a `HeadlessJsTaskContext` which in turn creates a `Handler`, ReactInstance destruction doesn't complete cleanly. ``` 2024-05-15 17:42:52.935 12681 27113 W fb4a.BridgelessReact: ReactHost{1}.getOrCreateDestroyTask(): React destruction failed. ReactInstance task faulted. Fault reason: Can't create handler inside thread Thread[pool-51-thread-1,5,main] that has not called Looper.prepare(). Destroy reason: FbReactInstanceHolder.destroyReactManager(): FbReactInstanceLogoutCleaner.clearReactInstanceData() ``` The fix is to not create our own Handler, but instead use the shared methods in UiThreadUtil. Changelog: [Android][Fixed] Fixed error thrown during ReactInstance teardown Reviewed By: cortinico Differential Revision: D57378247 fbshipit-source-id: a31dc8e35b5418a71b83c301973f12350f2ee01b
1 parent fd8eb48 commit e67d556

1 file changed

Lines changed: 5 additions & 13 deletions

File tree

packages/react-native/ReactAndroid/src/main/java/com/facebook/react/jstasks/HeadlessJsTaskContext.java

Lines changed: 5 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77

88
package com.facebook.react.jstasks;
99

10-
import android.os.Handler;
1110
import android.util.SparseArray;
1211
import com.facebook.infer.annotation.Assertions;
1312
import com.facebook.react.bridge.ReactContext;
@@ -52,7 +51,6 @@ public static HeadlessJsTaskContext getInstance(ReactContext context) {
5251
private final Set<HeadlessJsTaskEventListener> mHeadlessJsTaskEventListeners =
5352
new CopyOnWriteArraySet<>();
5453
private final AtomicInteger mLastTaskId = new AtomicInteger(0);
55-
private final Handler mHandler = new Handler();
5654
private final Set<Integer> mActiveTasks = new CopyOnWriteArraySet<>();
5755
private final Map<Integer, HeadlessJsTaskConfig> mActiveTaskConfigs = new ConcurrentHashMap<>();
5856
private final SparseArray<Runnable> mTaskTimeouts = new SparseArray<>();
@@ -194,9 +192,9 @@ public void run() {
194192
}
195193

196194
private void removeTimeout(int taskId) {
197-
Runnable timeout = mTaskTimeouts.get(taskId);
198-
if (timeout != null) {
199-
mHandler.removeCallbacks(timeout);
195+
Runnable runnable = mTaskTimeouts.get(taskId);
196+
if (runnable != null) {
197+
UiThreadUtil.removeOnUiThread(runnable);
200198
mTaskTimeouts.remove(taskId);
201199
}
202200
}
@@ -210,14 +208,8 @@ public synchronized boolean isTaskRunning(final int taskId) {
210208
}
211209

212210
private void scheduleTaskTimeout(final int taskId, long timeout) {
213-
Runnable runnable =
214-
new Runnable() {
215-
@Override
216-
public void run() {
217-
finishTask(taskId);
218-
}
219-
};
211+
Runnable runnable = () -> finishTask(taskId);
220212
mTaskTimeouts.append(taskId, runnable);
221-
mHandler.postDelayed(runnable, timeout);
213+
UiThreadUtil.runOnUiThread(runnable, timeout);
222214
}
223215
}

0 commit comments

Comments
 (0)