CLMonitor related crash - EXC_BAD_ACCESS (SIGSEGV)

Hello

I started using CLMonitor on my App, and I am noticing the following crash on Xcode Organizer for dozens of my app users:

Exception Subtype: KERN_INVALID_ADDRESS at 0x0000000000000001
Exception Codes: 0x0000000000000001, 0x0000000000000001
VM Region Info: 0x1 is not in any region.  Bytes before following region: ………….
      REGION TYPE                 START - END      [ VSIZE] PRT/MAX SHRMOD  REGION DETAIL
      UNUSED SPACE AT START
--->  
      __TEXT                   ………-…….. [  176K] r-x/r-x SM=COW  /var/containers/Bundle/Application/.........../MyApp
Termination Reason: SIGNAL 11 Segmentation fault: 11
Terminating Process: exc handler […..]

Thread 4 name:
Thread 4 Crashed:
0   libswiftCoreLocation.dylib    	0x000000021680b4c8 @objc completion handler block implementation for @escaping @callee_unowned @convention(block) (@unowned CLMonitor) -> () with result type CLMonitor + 44 (<compiler-generated>:0)
1   CoreLocation                  	0x0000000196cdddd4 __76-[CLMonitorConfiguration vendMonitorWithIdentityAndAuthorizationAttributes:]_block_invoke + 216 (CLMonitorConfiguration.m:195)
2   libdispatch.dylib             	0x0000000191138370 _dispatch_call_block_and_release + 32 (init.c:1549)
3   libdispatch.dylib             	0x000000019113a0d0 _dispatch_client_callout + 20 (object.m:576)
4   libdispatch.dylib             	0x00000001911416d8 _dispatch_lane_serial_drain + 744 (queue.c:3934)
5   libdispatch.dylib             	0x00000001911421e0 _dispatch_lane_invoke + 380 (queue.c:4025)
6   libdispatch.dylib             	0x000000019114d258 _dispatch_root_queue_drain_deferred_wlh + 288 (queue.c:7193)
7   libdispatch.dylib             	0x000000019114caa4 _dispatch_workloop_worker_thread + 540 (queue.c:6787)
8   libsystem_pthread.dylib       	0x0000000211933c7c _pthread_wqthread + 288 (pthread.c:2696)
9   libsystem_pthread.dylib       	0x0000000211930488 start_wqthread + 8

Does anyone have similar issue when using CLMonitor?

How can I debug / fix this issue?

Is it an CLMonitor API bug? Should I file a bug report?

Answered by DTS Engineer in 818774022

I attached a crash log with the details I can share for the moment

So, this crash log is a great example of why I always try to get a full log before trying to diagnose anything. It's very easy to focus on the threads that seem to be the source of the problem without realizing there are other concerns in play.

In this case, my biggest concern is the combination 6 threads and your main thread state:

32  MyMainModule    	0x00000001038d4064 +[MyMainModuleInitClass load] + 100 (MyMainModuleInitClass.m:32)
33  libobjc.A.dylib               	0x0000000186724714 load_images + 736 (objc-runtime-new.mm:3740)
34  dyld                          	0x00000001aedfad10 dyld4::RuntimeState::notifyObjCInit(dyld4::Loader const*) + 576 (DyldRuntimeState.cpp:2139)
35  dyld                          	0x00000001aee33908 dyld4::Loader::runInitializersBottomUp(dyld4::RuntimeState&, dyld3::Array&, dyld3::Array&) const + 300 (Loader.cpp:2316)
36  dyld                          	0x00000001aee338b4 dyld4::Loader::runInitializersBottomUp(dyld4::RuntimeState&, dyld3::Array&, dyld3::Array&) const + 216 (Loader.cpp:2309)
37  dyld                          	0x00000001aee352c8 dyld4::Loader::runInitializersBottomUpPlusUpwardLinks(dyld4::RuntimeState&) const::$_0::operator()() const + 180 (Loader.cpp:2330)
38  dyld                          	0x00000001aee00c00 dyld4::Loader::runInitializersBottomUpPlusUpwardLinks(dyld4::RuntimeState&) const + 412 (Loader.cpp:2326)
39  dyld                          	0x00000001aedf0280 dyld4::APIs::runAllInitializersForMain() + 296 (DyldAPIs.cpp:4150)
40  dyld                          	0x00000001aee04d10 dyld4::prepare(dyld4::APIs&, dyld3::MachOAnalyzer const*) + 3404 (dyldMain.cpp:902)
41  dyld                          	0x00000001aee299f8 dyld4::start(dyld4::KernelArgs*, void*, void*)::$_0::operator()() const + 544 (dyldMain.cpp:1322)
42  dyld                          	0x00000001aee22cb0 start + 2188 (dyldMain.cpp:1299)

Your app is currently in library load time and has not yet called main. In other words, you've kicked off most of your apps functionality, including initializing system framework like CoreLocation, BEFORE your app has initialized UIKit and started it's event loop.

The systems behavior in this state is basically... undefined. Most of our framework implicitly assume that they're running "in an app" and rely on a variety of implicit configuration/state that comes from that configuration. Lots of things do "work" (which is why your app works at all), but that's basically "accidental", NOT because of any special effort on the frameworks part.

Related to that point, I also noticed that your app crashing very early in a background launch:

Role:                Non UI
...
Date/Time:           2024-11-21 14:51:03.5555 +0100
Launch Time:         2024-11-21 14:51:03.1668 +0100

A few questions about this:

  • Is that consistent across all the crash logs you've gotten do some of the logs list a different role? Particularly foreground crashes?

  • Do you what might be triggering that launch (besides CoreLocation)?

The issue here is that the process a daemon uses to launch an app into the background is intended to work something like this:

  1. The daemon asks the system to launch the app.
  2. The app is launched.
  3. The app registers itself with the system early in UIApplicationMain().
  4. The app connects "back" to the daemon as part of it's normal start up process.

Focusing on point 4, most of our background APIs have some part of the documentation that includes a statement/verbiage similar to this:

"If your app actively receives and processes location updates and terminates, it should restart those APIs upon launch in order to continue receiving updates."

The issue here is that while CoreLocation initiates your app launch, it needs your app to connect BACK to it before it can actually "do" anything with your app. It needs that connection "back" from your app both to deliver events and, more importantly, to keep your app awake to have events delivered to it.

The problem with initializing at library load time (which is what your app is doing) is that you can "flip" the order of 3 & 4. What happens after that point depends entirely on the internal details of locationd and the daemon's that manage app lifetime. In the worst case, locationd is unable to properly "manage" your app because doing so relies on internal "infrastructure" that does actually exist yet (because that infrastructure is initialized in #3).

__
Kevin Elliott
DTS Engineer, CoreOS/Hardware

I started using CLMonitor on my App, and I am noticing the following crash on Xcode Organizer for dozens of my app users:

My guess is that there's something happening on your other threads that's disrupting CoreLocation. Please post the full crash log (or more than one) and I'll see what I can determine.

__
Kevin Elliott
DTS Engineer, CoreOS/Hardware

Thanks for your answer

Here are more details about the issue:

I have another thread having CLMonitor in its stacktrace:

Thread 3:
0   libsystem_kernel.dylib        	0x00000001d97f63e4 kevent_id + 8
1   libdispatch.dylib             	0x000000019115cb00 _dispatch_kq_poll + 228 (event_kevent.c:760)
2   libdispatch.dylib             	0x000000019115d50c _dispatch_event_loop_wait_for_ownership + 436 (event_kevent.c:2236)
3   libdispatch.dylib             	0x0000000191149a20 __DISPATCH_WAIT_FOR_QUEUE__ + 340 (queue.c:1704)
4   libdispatch.dylib             	0x00000001911495e8 _dispatch_sync_f_slow + 148 (queue.c:1799)
5   CoreLocation                  	0x0000000196df4a2c -[CLMonitor _getMonitoringRecords] + 188 (CLMonitor.mm:179)
6   libswiftCoreLocation.dylib    	0x000000021680ae54 CLMonitor.init(_:) + 84 (CLMonitor.swift:281)
7   libswiftCoreLocation.dylib    	0x000000021680a991 CLMonitor.__allocating_init(_:) + 1 (CLMonitor.swift:0)
8   MyModule    	0x0000000103918f55 closure #1 in MyService.setupTask() + 1 (MyService.swift:33)
9   MyModule    	0x00000001039145c1 $sxIeAgHr_xs5Error_pIegHrzo_s8SendableRzs5NeverORs_r0_lTRyt_Tg5TATQ0_ + 1 (/<compiler-generated>:0)
10  libswift_Concurrency.dylib    	0x0000000194b47e39 completeTaskWithClosure(swift::AsyncContext*, swift::SwiftError*) + 1 (Task.cpp:497)

no other thread mention CoreLocation or CLMonitor except these 2 threads.

and here is what my setupTask function look like

 func setupTask() {
        self.myTask = Task(priority: .high) {
            if #available(iOS 18.0, *) {
				// create my session
            }

            let monitor = await CLMonitor(myIdentifier)
            self.myMonitor = monitor
            for try await event in await monitor.events {
                if event.state == .unsatisfied {
                    let record = await monitor.record(for: event.identifier)
					// use record condition and lastEvent

                } else if event.state == .satisfied {
                    let record = await monitor.record(for: event.identifier)
					// use record condition and lastEvent
                }
            }
        }
    }

Here are more details about the issue: I have another thread having CLMonitor in its stacktrace:

I still need to see the full crash log to be able to offer the best guidance.

no other thread mention CoreLocation or CLMonitor except these 2 threads.

Having looked a very large number of random crash logs, it's almost impossible to predict what will or will not be interesting/useful in a crash log. This is why I've asked for the full log.

and here is what my setupTask function look like

I don't see any obvious issue in your code.

__
Kevin Elliott
DTS Engineer, CoreOS/Hardware

Thank you for your answer

I attached a crash log with the details I can share for the moment

I attached a crash log with the details I can share for the moment

So, this crash log is a great example of why I always try to get a full log before trying to diagnose anything. It's very easy to focus on the threads that seem to be the source of the problem without realizing there are other concerns in play.

In this case, my biggest concern is the combination 6 threads and your main thread state:

32  MyMainModule    	0x00000001038d4064 +[MyMainModuleInitClass load] + 100 (MyMainModuleInitClass.m:32)
33  libobjc.A.dylib               	0x0000000186724714 load_images + 736 (objc-runtime-new.mm:3740)
34  dyld                          	0x00000001aedfad10 dyld4::RuntimeState::notifyObjCInit(dyld4::Loader const*) + 576 (DyldRuntimeState.cpp:2139)
35  dyld                          	0x00000001aee33908 dyld4::Loader::runInitializersBottomUp(dyld4::RuntimeState&, dyld3::Array&, dyld3::Array&) const + 300 (Loader.cpp:2316)
36  dyld                          	0x00000001aee338b4 dyld4::Loader::runInitializersBottomUp(dyld4::RuntimeState&, dyld3::Array&, dyld3::Array&) const + 216 (Loader.cpp:2309)
37  dyld                          	0x00000001aee352c8 dyld4::Loader::runInitializersBottomUpPlusUpwardLinks(dyld4::RuntimeState&) const::$_0::operator()() const + 180 (Loader.cpp:2330)
38  dyld                          	0x00000001aee00c00 dyld4::Loader::runInitializersBottomUpPlusUpwardLinks(dyld4::RuntimeState&) const + 412 (Loader.cpp:2326)
39  dyld                          	0x00000001aedf0280 dyld4::APIs::runAllInitializersForMain() + 296 (DyldAPIs.cpp:4150)
40  dyld                          	0x00000001aee04d10 dyld4::prepare(dyld4::APIs&, dyld3::MachOAnalyzer const*) + 3404 (dyldMain.cpp:902)
41  dyld                          	0x00000001aee299f8 dyld4::start(dyld4::KernelArgs*, void*, void*)::$_0::operator()() const + 544 (dyldMain.cpp:1322)
42  dyld                          	0x00000001aee22cb0 start + 2188 (dyldMain.cpp:1299)

Your app is currently in library load time and has not yet called main. In other words, you've kicked off most of your apps functionality, including initializing system framework like CoreLocation, BEFORE your app has initialized UIKit and started it's event loop.

The systems behavior in this state is basically... undefined. Most of our framework implicitly assume that they're running "in an app" and rely on a variety of implicit configuration/state that comes from that configuration. Lots of things do "work" (which is why your app works at all), but that's basically "accidental", NOT because of any special effort on the frameworks part.

Related to that point, I also noticed that your app crashing very early in a background launch:

Role:                Non UI
...
Date/Time:           2024-11-21 14:51:03.5555 +0100
Launch Time:         2024-11-21 14:51:03.1668 +0100

A few questions about this:

  • Is that consistent across all the crash logs you've gotten do some of the logs list a different role? Particularly foreground crashes?

  • Do you what might be triggering that launch (besides CoreLocation)?

The issue here is that the process a daemon uses to launch an app into the background is intended to work something like this:

  1. The daemon asks the system to launch the app.
  2. The app is launched.
  3. The app registers itself with the system early in UIApplicationMain().
  4. The app connects "back" to the daemon as part of it's normal start up process.

Focusing on point 4, most of our background APIs have some part of the documentation that includes a statement/verbiage similar to this:

"If your app actively receives and processes location updates and terminates, it should restart those APIs upon launch in order to continue receiving updates."

The issue here is that while CoreLocation initiates your app launch, it needs your app to connect BACK to it before it can actually "do" anything with your app. It needs that connection "back" from your app both to deliver events and, more importantly, to keep your app awake to have events delivered to it.

The problem with initializing at library load time (which is what your app is doing) is that you can "flip" the order of 3 & 4. What happens after that point depends entirely on the internal details of locationd and the daemon's that manage app lifetime. In the worst case, locationd is unable to properly "manage" your app because doing so relies on internal "infrastructure" that does actually exist yet (because that infrastructure is initialized in #3).

__
Kevin Elliott
DTS Engineer, CoreOS/Hardware

CLMonitor related crash - EXC_BAD_ACCESS (SIGSEGV)
 
 
Q