Skip to content

Fix race in UiThreadUtil main handler lazy initialization - #58963

Closed
locnp-active wants to merge 1 commit into
react:mainfrom
locnp-active:fix-uithreadutil-lazy-race
Closed

locnp-active wants to merge 1 commit into
react:mainfrom
locnp-active:fix-uithreadutil-lazy-race

Conversation

@locnp-active

Copy link
Copy Markdown
Contributor

Summary:

UiThreadUtil keeps its main-thread Handler in a property delegated to lazy(LazyThreadSafetyMode.NONE):

private val mainHandler: Handler by
    lazy(LazyThreadSafetyMode.NONE) { Handler(Looper.getMainLooper()) }

NONE creates an UnsafeLazyImpl, whose getter is:

if (_value === UNINITIALIZED_VALUE) {
  _value = initializer!!()
  initializer = null
}
return _value as T

mainHandler is first read by whichever thread first calls runOnUiThread(), getUiThreadHandler() or removeOnUiThread(). isOnUiThread() and the assert* helpers only use Looper, so the main thread calling them does not initialize it. In practice the first reads usually come from background threads posting to the UI thread, such as the JS thread, the native modules thread, or a library's executor. When two of them make their first call at the same time:

  1. Thread A sees _value === UNINITIALIZED_VALUE and starts the initializer.
  2. Thread B also sees UNINITIALIZED_VALUE, because A has not written _value yet.
  3. A writes _value and sets initializer = null.
  4. B evaluates initializer!!() and throws NullPointerException.

The same NPE can happen without the two calls overlapping in time. _value and initializer are plain fields, so on a weakly ordered CPU (ARM) another thread can observe initializer == null before it observes the new _value.

The exception is thrown from the accessor Kotlin generates for the delegated property, so crash reports show the top frame as com.facebook.react.bridge.UiThreadUtil.getMainHandler. Only the first access in a process can race, so the crash is rare but fatal and usually happens during startup.

This was introduced in #50536 (1033584), which migrated UiThreadUtil to Kotlin. The Java implementation used double-checked locking on a volatile field. A reviewer suggested plain by lazy { }, which is synchronized by default, but the merged code uses LazyThreadSafetyMode.NONE. Every release from 0.80 to 0.88.0-rc.4 includes it.

This PR switches the property to LazyThreadSafetyMode.SYNCHRONIZED, restoring the guarantee of the Java implementation. The lock is only taken until the value is initialized. After that, reads are a single volatile read, so the runOnUiThread hot path is effectively unchanged.

Changelog:

[ANDROID] [FIXED] - Fix crash in UiThreadUtil when the main handler is first accessed from multiple threads at once

Test Plan:

The race only happens on the first access in a process and cannot be reproduced reliably in a unit test. It can be confirmed by:

  1. Kotlin stdlib: UnsafeLazyImpl (NONE) is documented as unsafe for multi-threaded access. SynchronizedLazyImpl (SYNCHRONIZED) guarantees a single initialization and safe publication.
  2. Bytecode: in a release APK built with React Native 0.86.0, UiThreadUtil.<clinit> creates the lazy with LazyThreadSafetyMode.NONE. With this change it uses SYNCHRONIZED.
  3. Behavior: the public API and the value returned are unchanged. The only difference is how the handler is initialized the first time.

@meta-cla

meta-cla Bot commented Oct 9, 2026

Copy link
Copy Markdown

Hi @locnp-active!

Thank you for your pull request and welcome to our community.

Action Required

In order to merge any pull request (code, docs, etc.), we require contributors to sign our Contributor License Agreement, and we don't seem to have one on file for you.

Process

In order for us to review and merge your suggested changes, please sign at https://code.facebook.com/cla. If you are contributing on behalf of someone else (eg your employer), the individual CLA may not be sufficient and your employer may need to sign the corporate CLA.

Once the CLA is signed, our tooling will perform checks and validations. Afterwards, the pull request will be tagged with CLA signed. The tagging process may take up to 1 hour after signing. Please give it that time before contacting us about it.

If you have received this in error or have any questions, please contact us at cla@meta.com. Thanks!

@meta-cla meta-cla Bot added the CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed. label Oct 9, 2026
@meta-cla

meta-cla Bot commented Oct 9, 2026

Copy link
Copy Markdown

Thank you for signing our Contributor License Agreement. We can now accept your code for this (and any) Meta Open Source project. Thanks!

@facebook-github-tools facebook-github-tools Bot added the Shared with Meta Applied via automation to indicate that an Issue or Pull Request has been shared with the team. label Oct 9, 2026
@cortinico

Copy link
Copy Markdown
Contributor

Why are you sending this PR? is there an observed crash that is actually happening?

The same NPE can happen without the two calls overlapping in time. _value and initializer are plain fields, so on a weakly ordered CPU (ARM) another thread can observe initializer == null before it observes the new _value.

I'm wondering if this is actually happening or not

@locnp-active

locnp-active commented Oct 19, 2026 •

Copy link
Copy Markdown
Contributor Author

@cortinico

is there an observed crash that is actually happening?

Yes, this is observed in production. Across several of our Android apps it's a fatal crash with this exact signature: ~20 reports from May to Oct 2026, starting after we moved from RN 0.79 to 0.83.2, and still present on 0.86.0. All devices are arm64 (Pixel 8a/10a/10 Pro, Galaxy S25, Moto G64y), Android 15–17.

It shows up through two call paths, both at cold start while ReactHostImpl is creating the instance on a background thread.

1. Headless JS (FCM background message) on the main thread (4 of 5 sampled events)

Caused by java.lang.NullPointerException:
  at kotlin.UnsafeLazyImpl.getValue(Lazy.kt:98)
  at com.facebook.react.bridge.UiThreadUtil.getMainHandler(UiThreadUtil.kt:18)
  at com.facebook.react.bridge.UiThreadUtil.runOnUiThread(UiThreadUtil.kt:57)
  at com.facebook.react.HeadlessJsTaskService.invokeStartTask(HeadlessJsTaskService.kt:82)
  at com.facebook.react.HeadlessJsTaskService.startTask(HeadlessJsTaskService.kt:75)
  at com.facebook.react.HeadlessJsTaskService.onStartCommand(HeadlessJsTaskService.kt:44)
  at android.app.ActivityThread.handleServiceArgs(ActivityThread.java:6450)
  ...
  at android.app.ActivityThread.main(ActivityThread.java:10343)

At the same moment, another thread is already past ReactChoreographer.initialize() (ReactInstance.kt:125 on 0.83.2, which goes through getMainHandler) and is building TurboModules:

pool-N-thread-1:
  ...
  at com.facebook.react.ReactPackageTurboModuleManagerDelegate$Builder.build(ReactPackageTurboModuleManagerDelegate.kt:247)
  at com.facebook.react.runtime.ReactInstance.<init>(ReactInstance.kt:174)
  at com.facebook.react.runtime.ReactHostImpl.getOrCreateReactInstanceTask$lambda$44$lambda$40(ReactHostImpl.kt:995)
  ...

So the main thread sees initializer == null even though the other thread has finished initializing the lazy. The two calls don't overlap; the main thread just doesn't see the write yet. That is the case described in the PR.

2. ReactChoreographer init on the background thread (0.86.0)

Fatal Exception: java.lang.NullPointerException:
  at kotlin.UnsafeLazyImpl.getValue(Lazy.kt:98)
  at com.facebook.react.bridge.UiThreadUtil.getMainHandler(UiThreadUtil.kt:18)
  at com.facebook.react.bridge.UiThreadUtil.runOnUiThread(UiThreadUtil.kt:57)
  at com.facebook.react.modules.core.ReactChoreographer._init_$lambda$2(ReactChoreographer.kt:70)
  at com.facebook.react.modules.core.ReactChoreographer.<init>(ReactChoreographer.kt:70)
  at com.facebook.react.modules.core.ReactChoreographer$Companion.initialize(ReactChoreographer.kt:130)
  at com.facebook.react.runtime.ReactInstance.<init>(ReactInstance.kt:134)
  at com.facebook.react.runtime.ReactHostImpl.getOrCreateReactInstanceTask$lambda$45$lambda$41(ReactHostImpl.kt:1052)
  ...
  at java.lang.Thread.run(Thread.java:1571)

I don't have a deterministic local repro; this is from production crash reports only.

Full stack trace of a representative event (RN 0.83.2, app identifiers redacted)
# Crashlytics
# Application: ********
# Platform: android
# Version: ******** (RN 0.83.2)
# Issue: ********
# Session: ********
# Date: 2026-10 (********)

Fatal Exception: java.lang.RuntimeException: Unable to start service io.invertase.firebase.messaging.ReactNativeFirebaseMessagingHeadlessService@******** with Intent { xflg=0x4 cmp=********/io.invertase.firebase.messaging.ReactNativeFirebaseMessagingHeadlessService (has extras) }
       at android.app.ActivityThread.handleServiceArgs(ActivityThread.java:6466)
       at android.app.ActivityThread.-$$Nest$mhandleServiceArgs()
       at android.app.ActivityThread$H.handleMessage(ActivityThread.java:3111)
       at android.os.Handler.dispatchMessage(Handler.java:132)
       at android.os.Looper.dispatchMessage(Looper.java:358)
       at android.os.Looper.loopOnce(Looper.java:288)
       at android.os.Looper.loop(Looper.java:392)
       at android.app.ActivityThread.main(ActivityThread.java:10343)
       at java.lang.reflect.Method.invoke(Method.java)
       at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:605)
       at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:972)

Caused by java.lang.NullPointerException:
       at kotlin.UnsafeLazyImpl.getValue(Lazy.kt:98)
       at com.facebook.react.bridge.UiThreadUtil.getMainHandler(UiThreadUtil.kt:18)
       at com.facebook.react.bridge.UiThreadUtil.runOnUiThread(UiThreadUtil.kt:57)
       at com.facebook.react.HeadlessJsTaskService.invokeStartTask(HeadlessJsTaskService.kt:82)
       at com.facebook.react.HeadlessJsTaskService.startTask(HeadlessJsTaskService.kt:75)
       at com.facebook.react.HeadlessJsTaskService.onStartCommand(HeadlessJsTaskService.kt:44)
       at android.app.ActivityThread.handleServiceArgs(ActivityThread.java:6450)
       at android.app.ActivityThread.-$$Nest$mhandleServiceArgs()
       at android.app.ActivityThread$H.handleMessage(ActivityThread.java:3111)
       at android.os.Handler.dispatchMessage(Handler.java:132)
       at android.os.Looper.dispatchMessage(Looper.java:358)
       at android.os.Looper.loopOnce(Looper.java:288)
       at android.os.Looper.loop(Looper.java:392)
       at android.app.ActivityThread.main(ActivityThread.java:10343)
       at java.lang.reflect.Method.invoke(Method.java)
       at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:605)
       at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:972)

pool-16-thread-1:
       at jdk.internal.misc.Unsafe.park(Unsafe.java)
       at java.util.concurrent.locks.LockSupport.park(LockSupport.java:371)
       at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionNode.block(AbstractQueuedSynchronizer.java:519)
       at java.util.concurrent.ForkJoinPool.unmanagedBlock(ForkJoinPool.java:3797)
       at java.util.concurrent.ForkJoinPool.managedBlock(ForkJoinPool.java:3738)
       at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:1712)
       at java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(ScheduledThreadPoolExecutor.java:1224)
       at java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(ScheduledThreadPoolExecutor.java:953)
       at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1080)
       at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1140)
       at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:652)
       at java.lang.Thread.run(Thread.java:1563)

queued-work-looper:
       at android.os.MessageQueue.nativePollOnce(MessageQueue.java)
       at android.os.MessageQueue.nextLegacy(MessageQueue.java:985)
       at android.os.MessageQueue.next(MessageQueue.java:1094)
       at android.os.Looper.loopOnce(Looper.java:222)
       at android.os.Looper.loop(Looper.java:392)
       at android.os.HandlerThread.run(HandlerThread.java:139)

Firebase Background Thread #3:
       at jdk.internal.misc.Unsafe.park(Unsafe.java)
       at java.util.concurrent.locks.LockSupport.park(LockSupport.java:371)
       at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionNode.block(AbstractQueuedSynchronizer.java:519)
       at java.util.concurrent.ForkJoinPool.unmanagedBlock(ForkJoinPool.java:3797)
       at java.util.concurrent.ForkJoinPool.managedBlock(ForkJoinPool.java:3738)
       at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:1712)
       at java.util.concurrent.LinkedBlockingQueue.take(LinkedBlockingQueue.java:435)
       at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1080)
       at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1140)
       at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:652)
       at com.google.firebase.concurrent.CustomThreadFactory.lambda$newThread$0(CustomThreadFactory.java:47)
       at java.lang.Thread.run(Thread.java:1563)

FileObserver:
       at android.os.FileObserver$ObserverThread.observe(FileObserver.java)
       at android.os.FileObserver$ObserverThread.run(FileObserver.java:116)

ScionFrontendApi:
       at jdk.internal.misc.Unsafe.park(Unsafe.java)
       at java.util.concurrent.locks.LockSupport.parkNanos(LockSupport.java:269)
       at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.awaitNanos(AbstractQueuedSynchronizer.java:1763)
       at java.util.concurrent.LinkedBlockingQueue.poll(LinkedBlockingQueue.java:460)
       at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1079)
       at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1140)
       at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:652)
       at java.lang.Thread.run(Thread.java:1563)

DefaultDispatcher-worker-3:
       at jdk.internal.misc.Unsafe.park(Unsafe.java)
       at java.util.concurrent.locks.LockSupport.parkNanos(LockSupport.java:410)
       at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.park(CoroutineScheduler.kt:858)
       at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.tryPark(CoroutineScheduler.kt:806)
       at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.runWorker(CoroutineScheduler.kt:754)
       at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run(CoroutineScheduler.kt:707)

mqt_v_js:
       at android.os.MessageQueue.nativePollOnce(MessageQueue.java)
       at android.os.MessageQueue.nextLegacy(MessageQueue.java:985)
       at android.os.MessageQueue.next(MessageQueue.java:1094)
       at android.os.Looper.loopOnce(Looper.java:222)
       at android.os.Looper.loop(Looper.java:392)
       at com.facebook.react.bridge.queue.MessageQueueThreadImpl$Companion.startNewBackgroundThread$lambda$0(MessageQueueThreadImpl.kt:152)
       at java.lang.Thread.run(Thread.java:1563)

HybridData DestructorThread:
       at java.lang.Object.wait(Object.java)
       at java.lang.Object.wait(Object.java:405)
       at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:207)
       at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:228)
       at com.facebook.jni.DestructorThread$1.run(DestructorThread.java:77)

DefaultDispatcher-worker-2:
       at jdk.internal.misc.Unsafe.park(Unsafe.java)
       at java.util.concurrent.locks.LockSupport.parkNanos(LockSupport.java:410)
       at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.park(CoroutineScheduler.kt:858)
       at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.tryPark(CoroutineScheduler.kt:806)
       at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.runWorker(CoroutineScheduler.kt:754)
       at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run(CoroutineScheduler.kt:707)

Firebase Background Thread #0:
       at jdk.internal.misc.Unsafe.park(Unsafe.java)
       at java.util.concurrent.locks.LockSupport.park(LockSupport.java:371)
       at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionNode.block(AbstractQueuedSynchronizer.java:519)
       at java.util.concurrent.ForkJoinPool.unmanagedBlock(ForkJoinPool.java:3797)
       at java.util.concurrent.ForkJoinPool.managedBlock(ForkJoinPool.java:3738)
       at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:1712)
       at java.util.concurrent.LinkedBlockingQueue.take(LinkedBlockingQueue.java:435)
       at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1080)
       at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1140)
       at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:652)
       at com.google.firebase.concurrent.CustomThreadFactory.lambda$newThread$0(CustomThreadFactory.java:47)
       at java.lang.Thread.run(Thread.java:1563)

GmsDynamite:
       at java.lang.Object.wait(Object.java)
       at java.lang.Object.wait(Object.java:405)
       at java.lang.Object.wait(Object.java:543)
       at com.google.android.gms.dynamite.zza.run(com.google.android.gms:play-services-basement@@18.9.0:2)

firebase-iid-executor:
       at jdk.internal.misc.Unsafe.park(Unsafe.java)
       at java.util.concurrent.locks.LockSupport.parkNanos(LockSupport.java:410)
       at java.util.concurrent.LinkedTransferQueue$DualNode.await(LinkedTransferQueue.java:452)
       at java.util.concurrent.SynchronousQueue$Transferer.xferLifo(SynchronousQueue.java:194)
       at java.util.concurrent.SynchronousQueue.xfer(SynchronousQueue.java:235)
       at java.util.concurrent.SynchronousQueue.poll(SynchronousQueue.java:338)
       at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1079)
       at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1140)
       at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:652)
       at com.google.android.gms.common.util.concurrent.zza.run(com.google.android.gms:play-services-basement@@18.9.0:2)
       at java.lang.Thread.run(Thread.java:1563)

Okio Watchdog:
       at java.lang.Object.wait(Object.java)
       at java.lang.Object.wait(Object.java:405)
       at java.lang.Object.wait(Object.java:543)
       at com.android.okhttp.okio.AsyncTimeout.awaitTimeout(AsyncTimeout.java:313)
       at com.android.okhttp.okio.AsyncTimeout.access$000(AsyncTimeout.java:42)
       at com.android.okhttp.okio.AsyncTimeout$Watchdog.run(AsyncTimeout.java:288)

ProcessStablePhenotypeFlag:
       at jdk.internal.misc.Unsafe.park(Unsafe.java)
       at java.util.concurrent.locks.LockSupport.park(LockSupport.java:371)
       at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionNode.block(AbstractQueuedSynchronizer.java:519)
       at java.util.concurrent.ForkJoinPool.unmanagedBlock(ForkJoinPool.java:3797)
       at java.util.concurrent.ForkJoinPool.managedBlock(ForkJoinPool.java:3738)
       at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:1712)
       at java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(ScheduledThreadPoolExecutor.java:1224)
       at java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(ScheduledThreadPoolExecutor.java:953)
       at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1080)
       at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1140)
       at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:652)
       at java.lang.Thread.run(Thread.java:1563)

Firebase Background Thread #2:
       at jdk.internal.misc.Unsafe.park(Unsafe.java)
       at java.util.concurrent.locks.LockSupport.park(LockSupport.java:371)
       at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionNode.block(AbstractQueuedSynchronizer.java:519)
       at java.util.concurrent.ForkJoinPool.unmanagedBlock(ForkJoinPool.java:3797)
       at java.util.concurrent.ForkJoinPool.managedBlock(ForkJoinPool.java:3738)
       at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:1712)
       at java.util.concurrent.LinkedBlockingQueue.take(LinkedBlockingQueue.java:435)
       at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1080)
       at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1140)
       at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:652)
       at com.google.firebase.concurrent.CustomThreadFactory.lambda$newThread$0(CustomThreadFactory.java:47)
       at java.lang.Thread.run(Thread.java:1563)

OkHttp ConnectionPool:
       at jdk.internal.misc.Unsafe.park(Unsafe.java)
       at java.util.concurrent.locks.LockSupport.parkNanos(LockSupport.java:269)
       at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.awaitNanos(AbstractQueuedSynchronizer.java:1763)
       at java.util.concurrent.LinkedBlockingQueue.poll(LinkedBlockingQueue.java:460)
       at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1079)
       at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1140)
       at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:652)
       at java.lang.Thread.run(Thread.java:1563)

pool-7-thread-1:
       at jdk.internal.misc.Unsafe.park(Unsafe.java)
       at java.util.concurrent.locks.LockSupport.park(LockSupport.java:371)
       at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionNode.block(AbstractQueuedSynchronizer.java:519)
       at java.util.concurrent.ForkJoinPool.unmanagedBlock(ForkJoinPool.java:3797)
       at java.util.concurrent.ForkJoinPool.managedBlock(ForkJoinPool.java:3738)
       at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:1712)
       at java.util.concurrent.LinkedBlockingQueue.take(LinkedBlockingQueue.java:435)
       at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1080)
       at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1140)
       at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:652)
       at java.lang.Thread.run(Thread.java:1563)

AsyncTask #2:
       at jdk.internal.misc.Unsafe.park(Unsafe.java)
       at java.util.concurrent.locks.LockSupport.park(LockSupport.java:371)
       at java.util.concurrent.LinkedTransferQueue$DualNode.await(LinkedTransferQueue.java:458)
       at java.util.concurrent.SynchronousQueue$Transferer.xferLifo(SynchronousQueue.java:194)
       at java.util.concurrent.SynchronousQueue.xfer(SynchronousQueue.java:235)
       at java.util.concurrent.SynchronousQueue.take(SynchronousQueue.java:318)
       at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1080)
       at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1140)
       at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:652)
       at java.lang.Thread.run(Thread.java:1563)

pool-27-thread-1:
       at android.net.wifi.WifiFrameworkInitializer.lambda$registerServiceWrappers$0(WifiFrameworkInitializer.java:54)
       at android.net.wifi.WifiFrameworkInitializer$$ExternalSyntheticLambda0.createService(D8$$SyntheticClass)
       at android.app.SystemServiceRegistry$201.createService(SystemServiceRegistry.java:3176)
       at android.app.SystemServiceRegistry$CachedServiceFetcher.getService(SystemServiceRegistry.java:3291)
       at android.app.SystemServiceRegistry.getSystemService(SystemServiceRegistry.java:2823)
       at android.app.ContextImpl.getSystemService(ContextImpl.java:2512)
       at android.content.ContextWrapper.getSystemService(ContextWrapper.java:1019)
       at com.reactnativecommunity.netinfo.ConnectivityReceiver.<init>(ConnectivityReceiver.java:80)
       at com.reactnativecommunity.netinfo.NetworkCallbackConnectivityReceiver.<init>(NetworkCallbackConnectivityReceiver.java:47)
       at com.reactnativecommunity.netinfo.NetInfoModule.<init>(NetInfoModule.java:30)
       at com.reactnativecommunity.netinfo.NetInfoPackage.createNativeModules(NetInfoPackage.java:21)
       at com.facebook.react.ReactPackageTurboModuleManagerDelegate.initialize(ReactPackageTurboModuleManagerDelegate.kt:87)
       at com.facebook.react.ReactPackageTurboModuleManagerDelegate.<init>(ReactPackageTurboModuleManagerDelegate.kt:45)
       at com.facebook.react.defaults.DefaultTurboModuleManagerDelegate.<init>(DefaultTurboModuleManagerDelegate.kt:35)
       at com.facebook.react.defaults.DefaultTurboModuleManagerDelegate.<init>(DefaultTurboModuleManagerDelegate.kt)
       at com.facebook.react.defaults.DefaultTurboModuleManagerDelegate$Builder.build(DefaultTurboModuleManagerDelegate.kt:63)
       at com.facebook.react.defaults.DefaultTurboModuleManagerDelegate$Builder.build(DefaultTurboModuleManagerDelegate.kt:43)
       at com.facebook.react.ReactPackageTurboModuleManagerDelegate$Builder.build(ReactPackageTurboModuleManagerDelegate.kt:247)
       at com.facebook.react.runtime.ReactInstance.<init>(ReactInstance.kt:174)
       at com.facebook.react.runtime.ReactHostImpl.getOrCreateReactInstanceTask$lambda$44$lambda$40(ReactHostImpl.kt:995)
       at com.facebook.react.runtime.internal.bolts.Task$Companion.completeImmediately$lambda$3(Task.kt:360)
       at com.facebook.react.runtime.internal.bolts.Executors$ImmediateExecutor.execute(Executors.kt:41)
       at com.facebook.react.runtime.internal.bolts.Task$Companion.completeImmediately(Task.kt:358)
       at com.facebook.react.runtime.internal.bolts.Task$Companion.access$completeImmediately(Task.kt:254)
       at com.facebook.react.runtime.internal.bolts.Task.continueWith(Task.kt:133)
       at com.facebook.react.runtime.internal.bolts.Task.continueWith$default(Task.kt:117)
       at com.facebook.react.runtime.internal.bolts.Task.onSuccess$lambda$12(Task.kt:176)
       at com.facebook.react.runtime.internal.bolts.Task$Companion.completeAfterTask$lambda$5(Task.kt:394)
       at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1154)
       at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:652)
       at java.lang.Thread.run(Thread.java:1563)

FinalizerDaemon:
       at java.lang.Object.wait(Object.java)
       at java.lang.Object.wait(Object.java:405)
       at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:207)
       at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:228)
       at java.lang.Daemons$FinalizerDaemon.runInternal(Daemons.java:350)
       at java.lang.Daemons$Daemon.run(Daemons.java:135)
       at java.lang.Thread.run(Thread.java:1563)

pool-15-thread-1:
       at jdk.internal.misc.Unsafe.park(Unsafe.java)
       at java.util.concurrent.locks.LockSupport.parkNanos(LockSupport.java:269)
       at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.awaitNanos(AbstractQueuedSynchronizer.java:1763)
       at java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(ScheduledThreadPoolExecutor.java:1236)
       at java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(ScheduledThreadPoolExecutor.java:953)
       at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1080)
       at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1140)
       at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:652)
       at java.lang.Thread.run(Thread.java:1563)

mqt_v_native:
       at android.os.MessageQueue.nativePollOnce(MessageQueue.java)
       at android.os.MessageQueue.nextLegacy(MessageQueue.java:985)
       at android.os.MessageQueue.next(MessageQueue.java:1094)
       at android.os.Looper.loopOnce(Looper.java:222)
       at android.os.Looper.loop(Looper.java:392)
       at com.facebook.react.bridge.queue.MessageQueueThreadImpl$Companion.startNewBackgroundThread$lambda$0(MessageQueueThreadImpl.kt:152)
       at java.lang.Thread.run(Thread.java:1563)

Firebase-Messaging-Topics-Io:
       at jdk.internal.misc.Unsafe.park(Unsafe.java)
       at java.util.concurrent.locks.LockSupport.park(LockSupport.java:371)
       at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionNode.block(AbstractQueuedSynchronizer.java:519)
       at java.util.concurrent.ForkJoinPool.unmanagedBlock(ForkJoinPool.java:3797)
       at java.util.concurrent.ForkJoinPool.managedBlock(ForkJoinPool.java:3738)
       at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:1712)
       at java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(ScheduledThreadPoolExecutor.java:1224)
       at java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(ScheduledThreadPoolExecutor.java:953)
       at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1080)
       at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1140)
       at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:652)
       at com.google.android.gms.common.util.concurrent.zza.run(com.google.android.gms:play-services-basement@@18.9.0:2)
       at java.lang.Thread.run(Thread.java:1563)

ReferenceQueueDaemon:
       at java.lang.Object.wait(Object.java)
       at java.lang.Object.wait(Object.java:405)
       at java.lang.Object.wait(Object.java:543)
       at java.lang.Daemons$ReferenceQueueDaemon.runInternal(Daemons.java:262)
       at java.lang.Daemons$Daemon.run(Daemons.java:135)
       at java.lang.Thread.run(Thread.java:1563)

MessengerIpcClient:
       at jdk.internal.misc.Unsafe.park(Unsafe.java)
       at java.util.concurrent.locks.LockSupport.park(LockSupport.java:371)
       at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionNode.block(AbstractQueuedSynchronizer.java:519)
       at java.util.concurrent.ForkJoinPool.unmanagedBlock(ForkJoinPool.java:3797)
       at java.util.concurrent.ForkJoinPool.managedBlock(ForkJoinPool.java:3738)
       at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:1712)
       at java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(ScheduledThreadPoolExecutor.java:1224)
       at java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(ScheduledThreadPoolExecutor.java:953)
       at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1080)
       at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1140)
       at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:652)
       at com.google.android.gms.common.util.concurrent.zza.run(com.google.android.gms:play-services-basement@@18.9.0:2)
       at java.lang.Thread.run(Thread.java:1563)

Firebase Background Thread #1:
       at dalvik.system.VMStack.getThreadStackTrace(VMStack.java)
       at java.lang.Thread.getStackTrace(Thread.java:2842)
       at java.lang.Thread.getAllStackTraces(Thread.java:2909)
       at com.google.firebase.crashlytics.internal.common.CrashlyticsReportDataCapture.populateThreadsList(CrashlyticsReportDataCapture.java:343)
       at com.google.firebase.crashlytics.internal.common.CrashlyticsReportDataCapture.populateExecutionData(CrashlyticsReportDataCapture.java:314)
       at com.google.firebase.crashlytics.internal.common.CrashlyticsReportDataCapture.populateEventApplicationData(CrashlyticsReportDataCapture.java:261)
       at com.google.firebase.crashlytics.internal.common.CrashlyticsReportDataCapture.captureEventData(CrashlyticsReportDataCapture.java:112)
       at com.google.firebase.crashlytics.internal.common.SessionReportingCoordinator.persistEvent(SessionReportingCoordinator.java:337)
       at com.google.firebase.crashlytics.internal.common.SessionReportingCoordinator.persistFatalEvent(SessionReportingCoordinator.java:130)
       at com.google.firebase.crashlytics.internal.common.CrashlyticsController$2.call(CrashlyticsController.java:218)
       at com.google.firebase.crashlytics.internal.common.CrashlyticsController$2.call(CrashlyticsController.java:204)
       at com.google.firebase.crashlytics.internal.concurrency.CrashlyticsWorker.lambda$submitTask$2(CrashlyticsWorker.java:118)
       at com.google.android.gms.tasks.zze.run(com.google.android.gms:play-services-tasks@@18.4.0:1)
       at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1154)
       at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:652)
       at com.google.firebase.concurrent.CustomThreadFactory.lambda$newThread$0(CustomThreadFactory.java:47)
       at java.lang.Thread.run(Thread.java:1563)

DefaultDispatcher-worker-1:
       at jdk.internal.misc.Unsafe.park(Unsafe.java)
       at java.util.concurrent.locks.LockSupport.parkNanos(LockSupport.java:410)
       at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.park(CoroutineScheduler.kt:858)
       at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.tryPark(CoroutineScheduler.kt:806)
       at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.runWorker(CoroutineScheduler.kt:754)
       at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run(CoroutineScheduler.kt:707)

WM.task-1:
       at jdk.internal.misc.Unsafe.park(Unsafe.java)
       at java.util.concurrent.locks.LockSupport.park(LockSupport.java:371)
       at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionNode.block(AbstractQueuedSynchronizer.java:519)
       at java.util.concurrent.ForkJoinPool.unmanagedBlock(ForkJoinPool.java:3797)
       at java.util.concurrent.ForkJoinPool.managedBlock(ForkJoinPool.java:3738)
       at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:1712)
       at java.util.concurrent.LinkedBlockingQueue.take(LinkedBlockingQueue.java:435)
       at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1080)
       at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1140)
       at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:652)
       at java.lang.Thread.run(Thread.java:1563)

GoogleApiHandler:
       at android.os.MessageQueue.nativePollOnce(MessageQueue.java)
       at android.os.MessageQueue.nextLegacy(MessageQueue.java:985)
       at android.os.MessageQueue.next(MessageQueue.java:1094)
       at android.os.Looper.loopOnce(Looper.java:222)
       at android.os.Looper.loop(Looper.java:392)
       at android.os.HandlerThread.run(HandlerThread.java:139)

WM.task-2:
       at jdk.internal.misc.Unsafe.park(Unsafe.java)
       at java.util.concurrent.locks.LockSupport.park(LockSupport.java:371)
       at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionNode.block(AbstractQueuedSynchronizer.java:519)
       at java.util.concurrent.ForkJoinPool.unmanagedBlock(ForkJoinPool.java:3797)
       at java.util.concurrent.ForkJoinPool.managedBlock(ForkJoinPool.java:3738)
       at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:1712)
       at java.util.concurrent.LinkedBlockingQueue.take(LinkedBlockingQueue.java:435)
       at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1080)
       at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1140)
       at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:652)
       at java.lang.Thread.run(Thread.java:1563)

Measurement Worker:
       at java.lang.Object.wait(Object.java)
       at java.lang.Object.wait(Object.java:405)
       at m7.vr.run(:com.google.android.gms.dynamite_measurementdynamite@263737035@26.37.37 (260400-0):67)

Firebase-Messaging-Init:
       at jdk.internal.misc.Unsafe.park(Unsafe.java)
       at java.util.concurrent.locks.LockSupport.park(LockSupport.java:371)
       at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionNode.block(AbstractQueuedSynchronizer.java:519)
       at java.util.concurrent.ForkJoinPool.unmanagedBlock(ForkJoinPool.java:3797)
       at java.util.concurrent.ForkJoinPool.managedBlock(ForkJoinPool.java:3738)
       at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:1712)
       at java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(ScheduledThreadPoolExecutor.java:1224)
       at java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(ScheduledThreadPoolExecutor.java:953)
       at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1080)
       at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1140)
       at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:652)
       at com.google.android.gms.common.util.concurrent.zza.run(com.google.android.gms:play-services-basement@@18.9.0:2)
       at java.lang.Thread.run(Thread.java:1563)

FinalizerWatchdogDaemon:
       at java.lang.Object.wait(Object.java)
       at java.lang.Object.wait(Object.java:405)
       at java.lang.Object.wait(Object.java:543)
       at java.lang.Daemons$FinalizerWatchdogDaemon.sleepUntilNeeded(Daemons.java:483)
       at java.lang.Daemons$FinalizerWatchdogDaemon.runInternal(Daemons.java:463)
       at java.lang.Daemons$Daemon.run(Daemons.java:135)
       at java.lang.Thread.run(Thread.java:1563)

@meta-codesync

meta-codesync Bot commented Oct 19, 2026

Copy link
Copy Markdown

@cortinico has imported this pull request. If you are a Meta employee, you can view this in D126040472.

@meta-codesync meta-codesync Bot closed this in 65b3e64 Oct 19, 2026
@meta-codesync meta-codesync Bot added the Merged This PR has been merged. label Oct 19, 2026
@meta-codesync

meta-codesync Bot commented Oct 19, 2026

Copy link
Copy Markdown

@cortinico merged this pull request in 65b3e64.

@react-native-bot

Copy link
Copy Markdown
Collaborator

This pull request was successfully merged by @locnp-active in 65b3e64

When will my fix make it into a release? | How to file a pick request?

@locnp-active

Copy link
Copy Markdown
Contributor Author

Thanks @cortinico and @javache for the review! Really appreciate you applying the PUBLICATION change and landing this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed. Merged This PR has been merged. Shared with Meta Applied via automation to indicate that an Issue or Pull Request has been shared with the team.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants