Springboard crashing when adding a lot of triggers to UNUserNotificationCenter

strangetimes picture strangetimes · Nov 16, 2016 · Viewed 6.9k times · Source

Save yourselves from hours of debugging, because I've just wasted 2 weeks after bug hunting mysterious app crashes. It turns out, if you're adding a lot o (see answer for more details) notification requests to the UNUserNotificationCenter, it will abruptly crash the Springboard. I haven't found a way around this yet, as the same code worked fine for iOS 9 and below. You can't seem to bulk-add notification requests like before either. Following is the crash I receive every single time (and so does hundreds of app users). Any idea what I could do instead of going back to using UILocalNotifications?

Incident Identifier: 17BC9D5B-AF74-4592-8427-038375C27AE7
CrashReporter Key:   a819553d1e72ee25a5ced9ddc79dbf00a7d3851f
Hardware Model:      iPad5,3
Process:             SpringBoard [2371]
Path:                /System/Library/CoreServices/SpringBoard.app/SpringBoard
Identifier:          com.apple.springboard
Version:             50 (1.0)
Code Type:           ARM-64 (Native)
Role:                Foreground
Parent Process:      launchd [1]
Coalition:           com.apple.springboard [71]


Date/Time:           2016-11-16 14:57:04.9159 +0400
Launch Time:         2016-11-16 14:49:20.9981 +0400
OS Version:          iPhone OS 10.0 (14A5309d)
Report Version:      104

Exception Type:  EXC_CRASH (SIGABRT)
Exception Codes: 0x0000000000000000, 0x0000000000000000
Exception Note:  EXC_CORPSE_NOTIFY
Triggered by Thread:  13

Filtered syslog:
None found

Thread 0 name:  Dispatch queue: com.apple.main-thread
Thread 0:
0   libsystem_kernel.dylib          0x0000000180624194 mach_msg_trap + 8
1   libsystem_kernel.dylib          0x0000000180624004 mach_msg + 72
2   CoreFoundation                  0x0000000180a61e8c __CFRunLoopServiceMachPort + 192
3   CoreFoundation                  0x0000000180a5faa8 __CFRunLoopRun + 1132
4   CoreFoundation                  0x000000018098f8d8 CFRunLoopRunSpecific + 444
5   GraphicsServices                0x0000000182396198 GSEventRunModal + 180
6   UIKit                           0x00000001869327c8 -[UIApplication _run] + 664
7   UIKit                           0x000000018692d534 UIApplicationMain + 208
8   libdyld.dylib                   0x00000001805305b8 start + 4

Thread 1 name:  com.apple.uikit.eventfetch-thread
Thread 1:
0   libsystem_kernel.dylib          0x0000000180624194 mach_msg_trap + 8
1   libsystem_kernel.dylib          0x0000000180624004 mach_msg + 72
2   CoreFoundation                  0x0000000180a61e8c __CFRunLoopServiceMachPort + 192
3   CoreFoundation                  0x0000000180a5faa8 __CFRunLoopRun + 1132
4   CoreFoundation                  0x000000018098f8d8 CFRunLoopRunSpecific + 444
5   Foundation                      0x000000018142ce3c -[NSRunLoop(NSRunLoop) runMode:beforeDate:] + 304
6   Foundation                      0x000000018144d92c -[NSRunLoop(NSRunLoop) runUntilDate:] + 96
7   UIKit                           0x000000018727af2c -[UIEventFetcher threadMain] + 136
8   Foundation                      0x00000001815293ac __NSThread__start__ + 1024
9   libsystem_pthread.dylib         0x00000001807079ec _pthread_body + 240
10  libsystem_pthread.dylib         0x00000001807078fc _pthread_body + 0
11  libsystem_pthread.dylib         0x0000000180704ef8 thread_start + 4

Thread 2:
0   libsystem_kernel.dylib          0x0000000180624194 mach_msg_trap + 8
1   libsystem_kernel.dylib          0x0000000180624004 mach_msg + 72
2   CoreFoundation                  0x0000000180a61e8c __CFRunLoopServiceMachPort + 192
3   CoreFoundation                  0x0000000180a5faa8 __CFRunLoopRun + 1132
4   CoreFoundation                  0x000000018098f8d8 CFRunLoopRunSpecific + 444
5   Foundation                      0x000000018142ce3c -[NSRunLoop(NSRunLoop) runMode:beforeDate:] + 304
6   Foundation                      0x0000000181481584 -[NSRunLoop(NSRunLoop) run] + 88
7   UIKit                           0x0000000186f73298 -[UIStatusBarServerThread main] + 840
8   Foundation                      0x00000001815293ac __NSThread__start__ + 1024
9   libsystem_pthread.dylib         0x00000001807079ec _pthread_body + 240
10  libsystem_pthread.dylib         0x00000001807078fc _pthread_body + 0
11  libsystem_pthread.dylib         0x0000000180704ef8 thread_start + 4

Thread 3:
0   libsystem_kernel.dylib          0x0000000180624194 mach_msg_trap + 8
1   libsystem_kernel.dylib          0x0000000180624004 mach_msg + 72
2   CoreFoundation                  0x0000000180a61e8c __CFRunLoopServiceMachPort + 192
3   CoreFoundation                  0x0000000180a5faa8 __CFRunLoopRun + 1132
4   CoreFoundation                  0x000000018098f8d8 CFRunLoopRunSpecific + 444
5   Foundation                      0x000000018142ce3c -[NSRunLoop(NSRunLoop) runMode:beforeDate:] + 304
6   CoreBrightness                  0x0000000190ec5d10 -[BrightnessSystemClientInternal main] + 1392
7   Foundation                      0x00000001815293ac __NSThread__start__ + 1024
8   libsystem_pthread.dylib         0x00000001807079ec _pthread_body + 240
9   libsystem_pthread.dylib         0x00000001807078fc _pthread_body + 0
10  libsystem_pthread.dylib         0x0000000180704ef8 thread_start + 4

Thread 4:
0   libsystem_kernel.dylib          0x0000000180624194 mach_msg_trap + 8
1   libsystem_kernel.dylib          0x0000000180624004 mach_msg + 72
2   CoreFoundation                  0x0000000180a61e8c __CFRunLoopServiceMachPort + 192
3   CoreFoundation                  0x0000000180a5faa8 __CFRunLoopRun + 1132
4   CoreFoundation                  0x000000018098f8d8 CFRunLoopRunSpecific + 444
5   SpringBoard                     0x00000001001a0b00 0x1000f0000 + 723712
6   libsystem_pthread.dylib         0x00000001807079ec _pthread_body + 240
7   libsystem_pthread.dylib         0x00000001807078fc _pthread_body + 0
8   libsystem_pthread.dylib         0x0000000180704ef8 thread_start + 4

Thread 5 name:  com.apple.springboard.icongeneration
Thread 5:
0   libsystem_kernel.dylib          0x0000000180624194 mach_msg_trap + 8
1   libsystem_kernel.dylib          0x0000000180624004 mach_msg + 72
2   CoreFoundation                  0x0000000180a61e8c __CFRunLoopServiceMachPort + 192
3   CoreFoundation                  0x0000000180a5faa8 __CFRunLoopRun + 1132
4   CoreFoundation                  0x000000018098f8d8 CFRunLoopRunSpecific + 444
5   SpringBoard                     0x00000001001a0c00 0x1000f0000 + 723968
6   libsystem_pthread.dylib         0x00000001807079ec _pthread_body + 240
7   libsystem_pthread.dylib         0x00000001807078fc _pthread_body + 0
8   libsystem_pthread.dylib         0x0000000180704ef8 thread_start + 4

Thread 6 name:  com.apple.CoreMotion.MotionThread
Thread 6:
0   libsystem_kernel.dylib          0x0000000180624194 mach_msg_trap + 8
1   libsystem_kernel.dylib          0x0000000180624004 mach_msg + 72
2   CoreFoundation                  0x0000000180a61e8c __CFRunLoopServiceMachPort + 192
3   CoreFoundation                  0x0000000180a5faa8 __CFRunLoopRun + 1132
4   CoreFoundation                  0x000000018098f8d8 CFRunLoopRunSpecific + 444
5   CoreFoundation                  0x00000001809dd094 CFRunLoopRun + 112
6   CoreMotion                      0x0000000187762994 0x187702000 + 395668
7   libsystem_pthread.dylib         0x00000001807079ec _pthread_body + 240
8   libsystem_pthread.dylib         0x00000001807078fc _pthread_body + 0
9   libsystem_pthread.dylib         0x0000000180704ef8 thread_start + 4

Thread 7 name:  SBWiFiManager callback thread
Thread 7:
0   libsystem_kernel.dylib          0x0000000180624194 mach_msg_trap + 8
1   libsystem_kernel.dylib          0x0000000180624004 mach_msg + 72
2   CoreFoundation                  0x0000000180a61e8c __CFRunLoopServiceMachPort + 192
3   CoreFoundation                  0x0000000180a5faa8 __CFRunLoopRun + 1132
4   CoreFoundation                  0x000000018098f8d8 CFRunLoopRunSpecific + 444
5   Foundation                      0x000000018142ce3c -[NSRunLoop(NSRunLoop) runMode:beforeDate:] + 304
6   Foundation                      0x0000000181481584 -[NSRunLoop(NSRunLoop) run] + 88
7   SpringBoard                     0x0000000100215e44 0x1000f0000 + 1203780
8   Foundation                      0x00000001815293ac __NSThread__start__ + 1024
9   libsystem_pthread.dylib         0x00000001807079ec _pthread_body + 240
10  libsystem_pthread.dylib         0x00000001807078fc _pthread_body + 0
11  libsystem_pthread.dylib         0x0000000180704ef8 thread_start + 4

Thread 8:
0   libsystem_kernel.dylib          0x0000000180624194 mach_msg_trap + 8
1   libsystem_kernel.dylib          0x0000000180624004 mach_msg + 72
2   CoreFoundation                  0x0000000180a61e8c __CFRunLoopServiceMachPort + 192
3   CoreFoundation                  0x0000000180a5faa8 __CFRunLoopRun + 1132
4   CoreFoundation                  0x000000018098f8d8 CFRunLoopRunSpecific + 444
5   Foundation                      0x000000018142ce3c -[NSRunLoop(NSRunLoop) runMode:beforeDate:] + 304
6   HomeKit                         0x00000001913e8974 -[_HMLocationHandler createLocationManager] + 508
7   Foundation                      0x00000001815293ac __NSThread__start__ + 1024
8   libsystem_pthread.dylib         0x00000001807079ec _pthread_body + 240
9   libsystem_pthread.dylib         0x00000001807078fc _pthread_body + 0
10  libsystem_pthread.dylib         0x0000000180704ef8 thread_start + 4

Thread 9:
0   libsystem_kernel.dylib          0x0000000180624194 mach_msg_trap + 8
1   libsystem_kernel.dylib          0x0000000180624004 mach_msg + 72
2   CoreFoundation                  0x0000000180a61e8c __CFRunLoopServiceMachPort + 192
3   CoreFoundation                  0x0000000180a5faa8 __CFRunLoopRun + 1132
4   CoreFoundation                  0x000000018098f8d8 CFRunLoopRunSpecific + 444
5   Foundation                      0x000000018142ce3c -[NSRunLoop(NSRunLoop) runMode:beforeDate:] + 304
6   CoreBrightness                  0x0000000190ec5d10 -[BrightnessSystemClientInternal main] + 1392
7   Foundation                      0x00000001815293ac __NSThread__start__ + 1024
8   libsystem_pthread.dylib         0x00000001807079ec _pthread_body + 240
9   libsystem_pthread.dylib         0x00000001807078fc _pthread_body + 0
10  libsystem_pthread.dylib         0x0000000180704ef8 thread_start + 4

Thread 10 name:  CommonUtilities-WiFi-Thread
Thread 10:
0   libsystem_kernel.dylib          0x0000000180624194 mach_msg_trap + 8
1   libsystem_kernel.dylib          0x0000000180624004 mach_msg + 72
2   CoreFoundation                  0x0000000180a61e8c __CFRunLoopServiceMachPort + 192
3   CoreFoundation                  0x0000000180a5faa8 __CFRunLoopRun + 1132
4   CoreFoundation                  0x000000018098f8d8 CFRunLoopRunSpecific + 444
5   CoreFoundation                  0x00000001809dd094 CFRunLoopRun + 112
6   CommonUtilities                 0x0000000182d10c20 0x182d0a000 + 27680
7   Foundation                      0x00000001815293ac __NSThread__start__ + 1024
8   libsystem_pthread.dylib         0x00000001807079ec _pthread_body + 240
9   libsystem_pthread.dylib         0x00000001807078fc _pthread_body + 0
10  libsystem_pthread.dylib         0x0000000180704ef8 thread_start + 4

Thread 11:
0   libsystem_kernel.dylib          0x0000000180642a88 __workq_kernreturn + 8
1   libsystem_pthread.dylib         0x000000018070549c _pthread_wqthread + 1440
2   libsystem_pthread.dylib         0x0000000180704ef0 start_wqthread + 4

Thread 12:
0   libsystem_kernel.dylib          0x0000000180642a88 __workq_kernreturn + 8
1   libsystem_pthread.dylib         0x000000018070549c _pthread_wqthread + 1440
2   libsystem_pthread.dylib         0x0000000180704ef0 start_wqthread + 4

Thread 13 name:  Dispatch queue: com.apple.frontboard.sqlite.database
Thread 13 Crashed:
0   libsystem_kernel.dylib          0x0000000180642014 __pthread_kill + 8
1   libsystem_pthread.dylib         0x00000001807094f0 pthread_kill + 112
2   libsystem_c.dylib               0x00000001805b64b8 abort + 140
3   libsystem_malloc.dylib          0x0000000180686a38 _nano_vet_and_size_of_live + 0
4   libsystem_malloc.dylib          0x0000000180687db8 nano_free + 220
5   libsqlite3.dylib                0x000000018103a5f8 0x180f95000 + 677368
6   libsqlite3.dylib                0x0000000180fbac9c 0x180f95000 + 154780
7   libsqlite3.dylib                0x0000000180fe6074 0x180f95000 + 331892
8   libsqlite3.dylib                0x0000000180fd70b0 sqlite3_step + 588
9   FrontBoard                      0x0000000190312ee4 __79-[_FBSqlitePreparedSimpleStatement executeWithBindings:resultRowHandler:error:]_block_invoke + 424
10  libdispatch.dylib               0x00000001804fd784 _dispatch_client_callout + 16
11  libdispatch.dylib               0x000000018050aca4 _dispatch_barrier_sync_f_invoke + 84
12  FrontBoard                      0x000000019031e0d0 -[FBSqliteDatabaseConnection performSyncWithDatabase:] + 80
13  FrontBoard                      0x0000000190312cbc -[_FBSqlitePreparedSimpleStatement executeWithBindings:resultRowHandler:error:] + 148
14  FrontBoard                      0x000000019035a4d8 -[FBSqliteApplicationDataStoreRepository _dbQueue_executeStatement:bindings:resultRowHandler:error:] + 80
15  FrontBoard                      0x000000019035a538 -[FBSqliteApplicationDataStoreRepository _dbQueue_executeStatement:bindings:resultRowHandler:] + 72
16  FrontBoard                      0x0000000190359374 -[FBSqliteApplicationDataStoreRepository _dbQueue_objectForKey:forApplication:] + 504
17  FrontBoard                      0x0000000190357a34 __81-[FBSqliteApplicationDataStoreRepository objectForKey:forApplication:withResult:]_block_invoke.44 + 40
18  libdispatch.dylib               0x00000001804fd784 _dispatch_client_callout + 16
19  libdispatch.dylib               0x000000018050aca4 _dispatch_barrier_sync_f_invoke + 84
20  FrontBoard                      0x0000000190357990 -[FBSqliteApplicationDataStoreRepository objectForKey:forApplication:withResult:] + 92
21  FrontBoard                      0x000000019038a5cc -[FBApplicationDataStoreInProcessRepositoryClient objectForKey:forApplication:withResult:checkPrefetch:] + 528
22  FrontBoardServices              0x00000001825c3e3c __40-[FBSApplicationDataStore objectForKey:]_block_invoke + 112
23  libdispatch.dylib               0x00000001804fd784 _dispatch_client_callout + 16
24  libdispatch.dylib               0x0000000180508f80 _dispatch_block_invoke_direct + 376
25  BaseBoard                       0x00000001825415a8 -[NSObject(BaseBoard) bs_performSynchronously:timeout:] + 144
26  FrontBoardServices              0x00000001825c3d7c -[FBSApplicationDataStore objectForKey:] + 224
27  FrontBoardServices              0x00000001825c4044 -[FBSApplicationDataStore safeObjectForKey:ofType:] + 32
28  FrontBoardServices              0x00000001825c41d4 -[FBSApplicationDataStore archivedObjectForKey:] + 64
29  FrontBoardServices              0x00000001825c4314 -[FBSApplicationDataStore safeArchivedObjectForKey:ofType:] + 32
30  UserNotificationsServer         0x000000019c52169c -[UNSPendingNotificationRepository _pendingNotificationDictionariesForBundleIdentifier:] + 140
31  UserNotificationsServer         0x000000019c5219d0 -[UNSPendingNotificationRepository setPendingNotificationRecords:forBundleIdentifier:] + 72
32  UserNotificationsServer         0x000000019c5249b4 -[UNSLocalNotificationClient _setPendingNotificationRecords:] + 500
33  UserNotificationsServer         0x000000019c5235c4 -[UNSLocalNotificationClient addPendingNotificationRecords:] + 1124
34  UserNotificationsServer         0x000000019c51d648 -[UNSNotificationSchedulingService _queue_addPendingNotificationRecords:forBundleIdentifier:] + 84
35  UserNotificationsServer         0x000000019c51c6b0 __108-[UNSNotificationSchedulingService addPendingNotificationRecords:forBundleIdentifier:withCompletionHandler:]_block_invoke + 36
36  libdispatch.dylib               0x00000001804fd7c4 _dispatch_call_block_and_release + 24
37  libdispatch.dylib               0x00000001804fd784 _dispatch_client_callout + 16
38  libdispatch.dylib               0x000000018050b880 _dispatch_queue_serial_drain + 928
39  libdispatch.dylib               0x0000000180500f6c _dispatch_queue_invoke + 652
40  libdispatch.dylib               0x000000018050bd7c _dispatch_queue_override_invoke + 360
41  libdispatch.dylib               0x000000018050d718 _dispatch_root_queue_drain + 572
42  libdispatch.dylib               0x000000018050d478 _dispatch_worker_thread3 + 124
43  libsystem_pthread.dylib         0x00000001807053f8 _pthread_wqthread + 1276
44  libsystem_pthread.dylib         0x0000000180704ef0 start_wqthread + 4

UPDATE: It doesn't seem to be based on a specific number of notifications. I just happened to have it trigger frequently given I had around 30 to 40 notifications registered while the app was in background (push notification, app refresh, app going to background etc) - since it was taking longer than usual to asynchronously add these alerts, the app would in the meanwhile let go of the background task identifier it had held. I've explained this in detail below, along with a workaround.

This bug has been acknowledged by Apple and marked as duplicate of a previously reported bug. I hope this gets fixed as it continues to cause problems in certain edge cases where the app launches in the background and times out soon after (during background content refreshes).

Answer

strangetimes picture strangetimes · Nov 16, 2016

I've found a workaround (bug already logged with Apple bug ID 29286162)

Essentially, it seems the SpringBoard crashes if the UNUserNotificationCenter is busy adding notifications and it hasn't finished doing so, while the user presses the home button to return to the SpringBoard. Clearly, somehow the thread is dying (well, possibly since I've got to let go of the background task identifier, hoping the UNUserNotificationCenter will happily consume the passed requests in its own system provided background thread), leaving the on-going asynchronous operation in limbo, causing Springboard to eventually crash. I now simply spawn a thread in a background task (UIBackgroundTaskIdentifier) and hold on to it till it's finished adding all the notifications. This results in zero crashes - confirmed also by all the users previously complaining the same.

  // arrTasksToSchedule -> holds UNNotificationRequests to add

  __block NSInteger volatile processedAlerts = 0;
  NSInteger totalToProcess = [arrTasksToSchedule count];
  UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter];
  for (UNNotificationRequest* notifRequest in arrTasksToSchedule) {
    [center addNotificationRequest:notifRequest withCompletionHandler:^(NSError * _Nullable error) {
      processedAlerts++;
    }];
  }

  // Let the runloop carry on processing events till we're done
  while (processedAlerts != totalToProcess) {
    [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];
  }

  // Okay we're done, and can now let go of our held UIBackgroundTaskIdentifier  

The documentation says nothing about background tasks, perils of using UNUserNotificationCenter in a background task or anything to do with multiple threads etc. I can only assume they didn't realize most apps do their notification registrations when their apps are sent to the background (or during a background content-refresh push notification).

Since the Springboard was crashing - crash reports were not being generated for the app itself. Users kept complaining and this was one of those terribly difficult situations where you've got no clue. I hope this saves someone a lot of headache.

UPDATE: Although the code above works just fine now, I've made a slightly modification as the while loop's condition may NOT be met in case the user closes the app and presses the power button to switch the screen off. In this case, the runloop obviously has nothing to process and will block. Instead, the following does the trick:

// Wait in a run loop
while (processedAlerts != totalToProcess) {
  [NSThread sleepForTimeInterval:0.15];

  // Don't use the following, as it will stop firing in case
  // the runloop has no events (such as touch events) firing
  // [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];
}