transistorsoft / transistorsoft/react-native-background-geolocation

[iOS] Watchdog Kill (0x8BADF00D) + Cold Start Gap >200m — New Architecture (TurboModules) on iOS 26 Beta

Open
#2,601 10 comments 2 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
TypeScript
Stars
2.9k
Forks
446
PR merge metrics
No merged PRs in 30d

Description

Required Reading
  • Confirmed
Plugin Version

5.1.1

Mobile operating-system(s)
  • iOS
  • Android
Device Manufacturer(s) and Model(s)

Apple iPhone 16 Pro Max (iPhone16,2)

Device operating-systems(s)

iOS 26.5 (23F77) — Beta

React Native / Expo version

React Native 0.81.5, Expo 54.0.33

What do you require assistance about?

Issue 1 — Watchdog Kill (0x8BADF00D) During Background Location Processing

Crash Details
  • Incident ID: DD1ED214-20D4-4CF9-A263-8344FAC4B274
  • Crash timestamp: 2026-05-31 13:01:25 +0530
  • Exception type: EXC_CRASH (SIGKILL)
  • Termination reason: FRONTBOARD – domain:10 code:0x8BADF00D
  • Watchdog event: scene-update (Background)
  • Process role: Non UI (background)
  • Process uptime at crash: ~850 seconds
  • Lock state duration: 122 seconds (device was locked)
  • Elapsed CPU at kill: 14.030s total (user 7.970s, system 6.060s), 44% CPU — application CPU was only 0.004s (0%), meaning watchdog fired on wall-clock time, not CPU burn. This is a locking/deadlock issue, not a performance issue.
Faulting Thread 0 — com.apple.main-thread (deadlocked)

Main thread stuck in _dispatch_once_wait, blocked on a lock triggered by a CoreLocation → LocationSupport callback:

0  __ulock_wait                            libsystem_kernel.dylib
1  _dlock_wait                             libdispatch.dylib
2  _dispatch_once_wait.cold.1              libdispatch.dylib
3  _dispatch_once_wait                     libdispatch.dylib
4  [imageOffset: 13028112]                 HarborSuite
5  [imageOffset: 12759580]                 HarborSuite
6  [imageOffset: 12785560]                 HarborSuite
7  [imageOffset: 240992]                   LocationSupport.framework
8  [imageOffset: 16936]                    LocationSupport.framework
9  [imageOffset: 5572]                     CoreLocation.framework
10 __CFRUNLOOP_IS_CALLING_OUT_TO_A_BLOCK__ CoreFoundation
11 __CFRunLoopDoBlocks                     CoreFoundation
12 __CFRunLoopRun                          CoreFoundation
13 _CFRunLoopRunSpecificWithOptions        CoreFoundation
14 GSEventRunModal                         GraphicsServices
15 -[UIApplication _run]                   UIKitCore
16 UIApplicationMain                       UIKitCore
Thread 3 — com.meta.react.turbomodulemanager.queue (blocked)

Simultaneously blocked in _dispatch_sync_f_slow trying to invoke TSLocationManager via ObjCTurboModule::performMethodInvocation, creating a circular deadlock with Thread 0:

0  __ulock_wait
1  _dispatch_thread_main_event_wait_slow
2  __DISPATCH_WAIT_FOR_QUEUE__
3  _dispatch_sync_f_slow
4–9 [HarborSuite: 13205856, 13029092, 13028192, 111076, 17840, 13028112]
10 [HarborSuite: 12777140 → 12923764 → 10298968]
11 __invoking___
12 -[NSInvocation invoke]
13 -[NSInvocation invokeWithTarget:]
14 invocation function for block in ObjCTurboModule::performMethodInvocation
15 ObjCTurboModule::performMethodInvocation::$_1::operator()
16 _dispatch_call_block_and_release
   _dispatch_client_callout
   _dispatch_lane_serial_drain
   _dispatch_lane_invoke
   _dispatch_root_queue_drain_deferred_wlh
   _dispatch_workloop_worker_thread
   _pthread_wqthread
   start_wqthread
Root Cause Analysis

TSLocationManager delivers a location event to the main thread (CoreLocation → LocationSupport callback), which hits a dispatch_once guarded section inside HarborSuite. Simultaneously, the TurboModule manager queue attempts a synchronous dispatch onto the main thread to invoke TSLocationManager via ObjCTurboModule::performMethodInvocation. Both threads are waiting for a lock the other holds → deadlock → iOS watchdog kills the process.

This appears specific to or exacerbated by New Architecture (TurboModules) and possibly iOS 26 beta where LocationSupport.framework behaviour may have changed.

Full .ips crash log attached.


Issue 2 — Cold Start Location Gap Exceeds Documented ~200 m

Description

After a cold start (process killed and relaunched by iOS), the first recorded location is significantly farther than the documented ~200 m from the last known position, causing a large visible gap in the track.

Screenshot attached showing the gap on the map.

Steps to Reproduce
  1. Start background tracking.
  2. Move continuously so locations are being recorded.
  3. Force-kill the app from the app switcher (or let iOS kill it).
  4. Relaunch the app (cold start).
  5. Compare the last pre-kill location with the first post-relaunch location.
Expected Behaviour

Cold-start gap of at most ~200 m as documented.

Actual Behaviour

Gap is substantially larger — observed several hundred meters to over 1 km in some cases.

Additional Context
  • Device: iPhone 16 Pro Max (A18 Pro chip), iOS 26 beta.
  • Using New Architecture (TurboModules) — module initialization delay on cold start may be pushing the first location callback further out.
  • expo-location (19.0.8) and expo-task-manager (14.0.9) are present alongside react-native-background-geolocation. Possible conflict in location session ownership on cold start.
  • TSLocationManager native pod: 4.1.7
  • Distribution: TestFlight (beta), App version: 2.0.8 (build 17)
[Optional] Plugin Code and/or Config
Image Image
const buildConfig = (token) => ({
  // ── Accuracy ────────────────────────────────────────────────────────────
  desiredAccuracy: BackgroundGeolocation.DesiredAccuracy.High,
  distanceFilter: 10,
  disableElasticity: true, // consistent tracking at all speeds
  elasticityMultiplier: 1,
  motionTriggerDelay: 0, // record immediately on motion
  disableLocationAuthorizationAlert: Platform.OS == "ios", // ONLY Android device get device default turn on location popup

  // ── Persistence: survive app kill + reboot ──────────────────────────────
  stopOnTerminate: false,
  startOnBoot: true,
  enableHeadless: true,

  locationAuthorizationRequest: "Always",

  // ── Activity recognition ────────────────────────────────────────────────
  stopTimeout: 5,

  // ── Offline SQLite buffer ───────────────────────────────────────────────
  maxRecordsToPersist: -1, // unlimited — never discard data
  maxDaysToPersist: 2, // keep 2 days of buffered data

  // ── Sync: one POST per location ─────────────────────────────────────────
  autoSync: !!token,
  autoSyncThreshold: 20,
  batchSync: true,
  maxBatchSize: 20,

  // ── HTTP ────────────────────────────────────────────────────────────────
  url: `${BASE_URL}/user-location-tracking/ingest`,
  method: "POST",
  httpRootProperty: ".",
  headers: token ? { Authorization: `Bearer ${token}` } : {},
  // Initial extras — kept in sync with RN AppState by wireAppStateToExtras().
  extras: { app_state: APP_STATE.FOREGROUND },

  // ── Android: foreground service + battery survival ──────────────────────
  foregroundService: true,
  notification: {
    title: "Harbor Suite - Work Location",
    text: "Location tracking is active for your work activities.",
    channelName: "Location Tracking",
    sticky: true,
  },
  locationUpdateInterval: 5000,
  fastestLocationUpdateInterval: 2000,
  deferTime: 0,

  // ── Heartbeat ───────────────────────────────────────────────────────────
  heartbeatInterval: 60,

  // ── iOS ─────────────────────────────────────────────────────────────────
  preventSuspend: true,
  activityType: BackgroundGeolocation.ActivityType.OtherNavigation,
  pausesLocationUpdatesAutomatically: false,
  showsBackgroundLocationIndicator: true,
  useSignificantChangesOnly: false,
  locationTimeout: 30,

  // ── Logging ─────────────────────────────────────────────────────────────
  debug: false,
  logLevel: BackgroundGeolocation.LogLevel.Verbose,
});
[Optional] Relevant log output

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with the attached .ips crash log and trace the interaction between the CoreLocation/LocationSupport callback, TSLocationManager, and the React Native TurboModule queue. Reproduce the watchdog and cold-start scenarios using the reported configuration, then verify that background processing no longer deadlocks and that the post-relaunch location gap meets the documented expectation.

Written by the indexing model from the issue text.

Assessment

Tech stack
ios, react-native, typescript
Domain
mobile
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
42/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.