BODY:
Description
On Android, OneSignal.initialize(appId) can permanently deadlock the main/UI thread. The app never recovers — the SDK's own ANR watchdog (OtelAnrDetector) detects and reports it as "OneSignal-related", but the main thread stays blocked (observed past 50s+ before we killed the process).
Environment
onesignal_flutter: 5.5.4
- Native Android SDK (bundled):
com.onesignal:OneSignal:5.8.1
- Android 15 (API 35), physical device
- Flutter (stable channel)
Stack trace (from device log during the hang)
W/MIUIScout App: Enter APP_SCOUT_HANG state
W/MIUIScout App: Event:APP_SCOUT_HANG Thread:main backtrace:
at jdk.internal.misc.Unsafe.park(Native Method)
at java.util.concurrent.locks.LockSupport.parkNanos(LockSupport.java:276)
at kotlinx.coroutines.BlockingCoroutine.joinBlocking(Builders.kt:98)
at kotlinx.coroutines.BuildersKt__BuildersKt.runBlocking(Builders.kt:69)
at kotlinx.coroutines.BuildersKt.runBlocking(...)
at com.onesignal.internal.OneSignalImp.waitForInit(OneSignalImp.kt:447)
at com.onesignal.internal.OneSignalImp.waitForInit$default(OneSignalImp.kt:446)
at com.onesignal.internal.OneSignalImp.waitAndReturn(OneSignalImp.kt:531)
at com.onesignal.internal.OneSignalImp.getServiceWithFeatureGate(OneSignalImp.kt:537)
at com.onesignal.internal.OneSignalImp.getInAppMessages(OneSignalImp.kt:131)
at com.onesignal.OneSignal.getInAppMessages(OneSignal.kt:78)
at com.onesignal.flutter.OneSignalInAppMessages.lifecycleInit(OneSignalInAppMessages.java:100)
at com.onesignal.flutter.OneSignalInAppMessages.onMethodCall(OneSignalInAppMessages.java:52)
at io.flutter.plugin.common.MethodChannel$IncomingMethodCallHandler.onMessage(MethodChannel.java:267)
at io.flutter.embedding.engine.dart.DartMessenger.invokeHandler(DartMessenger.java:286)
...
at android.os.Looper.loop(Looper.java:337)
at android.app.ActivityThread.main(ActivityThread.java:9682)
Followed by the SDK's own watchdog:
W/OneSignal: [OneSignal-ANR-Watchdog] OtelAnrDetector: ⚠️ ANR detected! Main thread unresponsive for 5931ms
I/OneSignal: [OneSignal-ANR-Watchdog] OtelAnrDetector: OneSignal-related ANR detected, reporting...
D/OneSignal: [OneSignal-ANR-Watchdog] OtelAnrDetector: ANR still ongoing (16032ms), but already reported recently (10101ms ago)
This repeats indefinitely — the main thread never recovers.
Root cause (as far as we can trace)
OneSignal.initialize() in the Dart plugin (onesignal_flutter 5.5.4) does:
static Future<void> initialize(String appId) async {
await _channel.invokeMethod('OneSignal#initialize', {'appId': appId});
await Future.wait([
InAppMessages.lifecycleInit(),
User.lifecycleInit(),
User.pushSubscription.lifecycleInit(),
Notifications.lifecycleInit(),
]);
}
InAppMessages.lifecycleInit() calls into native getInAppMessages(), which internally calls getServiceWithFeatureGate() -> waitForInit(), which does a kotlinx.coroutines.runBlocking wait on the calling thread. Since this call arrives via the Flutter MethodChannel handler, it executes on the Android main/UI thread. If the SDK's own internal async init hasn't fully completed by the time this runs, and that init itself needs the main thread's Looper to signal completion, this becomes a genuine self-deadlock rather than just a slow/blocking wait.
Reproduction
- Fresh/cold install of an app calling
await OneSignal.initialize(appId) early in app startup (e.g. right after WidgetsBinding first frame).
- On a "cold" OneSignal SDK state (e.g. after a full reinstall rather than an incremental update), the internal init appears to take long enough for the race to manifest as a full deadlock rather than a brief hang.
- Main thread never recovers; app is stuck on whatever UI was showing (in our case, a splash screen).
Expected behavior
OneSignal.initialize() should never be able to deadlock the calling thread, even during a cold/slow internal init.
Additional notes
- We deliberately tested downgrading to a much older version of an unrelated native dependency in our app (which forced a fresh app reinstall on the test device) and that is what surfaced this as a full deadlock rather than an intermittent slow path — suggesting this is a race that's more likely to manifest on a cold SDK-state install.
- We previously pinned
onesignal_flutter to 5.5.4 specifically because 5.6.3 broke iOS pod install for us, so we haven't been able to test whether this is fixed in later native SDK versions (5.6.3 bundles native 5.9.5).
Happy to provide a minimal repro project if useful.
Second confirmation (separate run, prod entrypoint, same device)
Reproduced again on a completely fresh install (lib/main.dart, prod flavor) with the identical stack trace:
D/OneSignal: [main] Calling deprecated initWithContextSuspend(context: ...MainActivity@..., appId: 4c4758cb-...)
D/OneSignal: [main] initWithContext: SDK already initialized or in progress
...
W/MIUIScout App: Event:APP_SCOUT_HANG Thread:main backtrace:
at kotlinx.coroutines.BuildersKt.runBlocking(...)
at com.onesignal.internal.OneSignalImp.waitForInit(OneSignalImp.kt:447)
at com.onesignal.internal.OneSignalImp.getServiceWithFeatureGate(OneSignalImp.kt:537)
at com.onesignal.internal.OneSignalImp.getInAppMessages(OneSignalImp.kt:131)
at com.onesignal.OneSignal.getInAppMessages(OneSignal.kt:78)
at com.onesignal.flutter.OneSignalInAppMessages.lifecycleInit(OneSignalInAppMessages.java:100)
...
W/OneSignal: [OneSignal-ANR-Watchdog] OtelAnrDetector: ⚠️ ANR detected! Main thread unresponsive for 5321ms
D/OneSignal: [OneSignal-ANR-Watchdog] OtelAnrDetector: ANR still ongoing (17533ms), but already reported recently (12212ms ago)
Notably, right before the hang, the SDK logs "Calling deprecated initWithContextSuspend" followed by "initWithContext: SDK already initialized or in progress" — logged from a single await OneSignal.initialize(appId) call in our Dart code (no native-side init call exists anywhere in our app; confirmed no manual init in MainActivity/Application/manifest). This suggests the internal bootstrap path itself re-enters or races against its own in-progress init state, which may be related to why waitForInit() then blocks forever.
This reproduces consistently (2/2 fresh installs so far) across both our dev and prod Flutter entrypoints on the same physical Android 15 device.
BODY:
Description
On Android,
OneSignal.initialize(appId)can permanently deadlock the main/UI thread. The app never recovers — the SDK's own ANR watchdog (OtelAnrDetector) detects and reports it as "OneSignal-related", but the main thread stays blocked (observed past 50s+ before we killed the process).Environment
onesignal_flutter: 5.5.4com.onesignal:OneSignal:5.8.1Stack trace (from device log during the hang)
Followed by the SDK's own watchdog:
This repeats indefinitely — the main thread never recovers.
Root cause (as far as we can trace)
OneSignal.initialize()in the Dart plugin (onesignal_flutter5.5.4) does:InAppMessages.lifecycleInit()calls into nativegetInAppMessages(), which internally callsgetServiceWithFeatureGate()->waitForInit(), which does akotlinx.coroutines.runBlockingwait on the calling thread. Since this call arrives via the FlutterMethodChannelhandler, it executes on the Android main/UI thread. If the SDK's own internal async init hasn't fully completed by the time this runs, and that init itself needs the main thread's Looper to signal completion, this becomes a genuine self-deadlock rather than just a slow/blocking wait.Reproduction
await OneSignal.initialize(appId)early in app startup (e.g. right afterWidgetsBindingfirst frame).Expected behavior
OneSignal.initialize()should never be able to deadlock the calling thread, even during a cold/slow internal init.Additional notes
onesignal_flutterto 5.5.4 specifically because 5.6.3 broke iOS pod install for us, so we haven't been able to test whether this is fixed in later native SDK versions (5.6.3 bundles native5.9.5).Happy to provide a minimal repro project if useful.
Second confirmation (separate run, prod entrypoint, same device)
Reproduced again on a completely fresh install (
lib/main.dart, prod flavor) with the identical stack trace:Notably, right before the hang, the SDK logs
"Calling deprecated initWithContextSuspend"followed by"initWithContext: SDK already initialized or in progress"— logged from a singleawait OneSignal.initialize(appId)call in our Dart code (no native-side init call exists anywhere in our app; confirmed no manual init inMainActivity/Application/manifest). This suggests the internal bootstrap path itself re-enters or races against its own in-progress init state, which may be related to whywaitForInit()then blocks forever.This reproduces consistently (2/2 fresh installs so far) across both our dev and prod Flutter entrypoints on the same physical Android 15 device.