From e67d5560cfd35f07ce74cfcc12555346a6f0e865 Mon Sep 17 00:00:00 2001 From: Pieter De Baets Date: Tue, 21 May 2024 06:37:28 -0700 Subject: [PATCH] Fix HeadlessJsTaskContext creating Handler on background thread (#44582) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/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 --- .../react/jstasks/HeadlessJsTaskContext.java | 18 +++++------------- 1 file changed, 5 insertions(+), 13 deletions(-) diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/jstasks/HeadlessJsTaskContext.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/jstasks/HeadlessJsTaskContext.java index 0b6294ba956..e4350d34cd9 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/jstasks/HeadlessJsTaskContext.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/jstasks/HeadlessJsTaskContext.java @@ -7,7 +7,6 @@ package com.facebook.react.jstasks; -import android.os.Handler; import android.util.SparseArray; import com.facebook.infer.annotation.Assertions; import com.facebook.react.bridge.ReactContext; @@ -52,7 +51,6 @@ public class HeadlessJsTaskContext { private final Set mHeadlessJsTaskEventListeners = new CopyOnWriteArraySet<>(); private final AtomicInteger mLastTaskId = new AtomicInteger(0); - private final Handler mHandler = new Handler(); private final Set mActiveTasks = new CopyOnWriteArraySet<>(); private final Map mActiveTaskConfigs = new ConcurrentHashMap<>(); private final SparseArray mTaskTimeouts = new SparseArray<>(); @@ -194,9 +192,9 @@ public class HeadlessJsTaskContext { } private void removeTimeout(int taskId) { - Runnable timeout = mTaskTimeouts.get(taskId); - if (timeout != null) { - mHandler.removeCallbacks(timeout); + Runnable runnable = mTaskTimeouts.get(taskId); + if (runnable != null) { + UiThreadUtil.removeOnUiThread(runnable); mTaskTimeouts.remove(taskId); } } @@ -210,14 +208,8 @@ public class HeadlessJsTaskContext { } private void scheduleTaskTimeout(final int taskId, long timeout) { - Runnable runnable = - new Runnable() { - @Override - public void run() { - finishTask(taskId); - } - }; + Runnable runnable = () -> finishTask(taskId); mTaskTimeouts.append(taskId, runnable); - mHandler.postDelayed(runnable, timeout); + UiThreadUtil.runOnUiThread(runnable, timeout); } }