CoreData/CloudKit 0xdead10cc

I’m getting a 0xdead10cc crash in a basic CoreData/CloudKit application. I only have one CoreData save call and its made when the app is in the foreground and it's minor so I don't think its being caused by that. My best guess is that it's related to background syncing of CloudKit. Does anyone know how to fix it? I've been advised that adding the following code around any saves will fix it, but it seems weird that this is the solution. I would expect the inner CoreData/CloudKit engine to handle this.

ProcessInfo().performActivity(reason: "Persisting to context") {
    // Save to context here
}

Here is the crashing thread

Thread 7:
0   libsystem_kernel.dylib        	0x00000001edc086f4 guarded_pwrite_np + 8 (:-1)
1   libsqlite3.dylib              	0x00000001ca71b6e4 seekAndWrite + 456 (sqlite3.c:44287)
2   libsqlite3.dylib              	0x00000001ca6d5df4 unixWrite + 180 (sqlite3.c:44365)
3   libsqlite3.dylib              	0x00000001ca723b90 pagerWalFrames + 872 (sqlite3.c:67093)
4   libsqlite3.dylib              	0x00000001ca6d5b14 sqlite3PagerCommitPhaseOne + 316 (sqlite3.c:70409)
5   libsqlite3.dylib              	0x00000001ca6c6494 sqlite3BtreeCommitPhaseOne + 172 (sqlite3.c:81106)
6   libsqlite3.dylib              	0x00000001ca6c605c vdbeCommit + 1136 (sqlite3.c:94124)
7   libsqlite3.dylib              	0x00000001ca69f778 sqlite3VdbeHalt + 1340 (sqlite3.c:94534)
8   libsqlite3.dylib              	0x00000001ca6c0618 sqlite3VdbeExec + 42648 (sqlite3.c:103922)
9   libsqlite3.dylib              	0x00000001ca6b56c0 sqlite3_step + 960 (sqlite3.c:97886)
10  CoreData                      	0x00000001a459ab38 _execute + 128 (NSSQLiteConnection.m:4614)
11  CoreData                      	0x00000001a45fe004 -[NSSQLiteConnection commitTransaction] + 728 (NSSQLiteConnection.m:3278)
12  CoreData                      	0x00000001a469888c _executeGenerateObjectIDRequest + 388 (NSSQLCore_Functions.m:6021)
13  CoreData                      	0x00000001a46986a4 -[NSSQLGenerateObjectIDRequestContext executeRequestCore:] + 28 (NSSQLObjectIDRequestContext.m:42)
14  CoreData                      	0x00000001a45fb380 -[NSSQLStoreRequestContext executeRequestUsingConnection:] + 240 (NSSQLStoreRequestContext.m:183)
15  CoreData                      	0x00000001a45fb0a8 __52-[NSSQLDefaultConnectionManager handleStoreRequest:]_block_invoke + 60 (NSSQLConnectionManager.m:307)
16  CoreData                      	0x00000001a45fafe0 __37-[NSSQLiteConnection performAndWait:]_block_invoke + 48 (NSSQLiteConnection.m:755)
17  libdispatch.dylib             	0x00000001a4357fa8 _dispatch_client_callout + 20 (object.m:576)
18  libdispatch.dylib             	0x00000001a43677fc _dispatch_lane_barrier_sync_invoke_and_complete + 56 (queue.c:1104)
19  CoreData                      	0x00000001a45b5ba4 -[NSSQLiteConnection performAndWait:] + 176 (NSSQLiteConnection.m:752)
20  CoreData                      	0x00000001a45b5a68 -[NSSQLDefaultConnectionManager handleStoreRequest:] + 248 (NSSQLConnectionManager.m:302)
21  CoreData                      	0x00000001a45b5938 -[NSSQLCoreDispatchManager routeStoreRequest:] + 228 (NSSQLCoreDispatchManager.m:60)
22  CoreData                      	0x00000001a45b573c -[NSSQLCore dispatchRequest:withRetries:] + 172 (NSSQLCore.m:4044)
23  CoreData                      	0x00000001a46737b4 -[NSSQLCore _obtainPermanentIDsForObjects:withNotification:error:] + 1324 (NSSQLCore.m:2830)
24  CoreData                      	0x00000001a460ba98 -[NSSQLCore _prepareForExecuteRequest:withContext:error:] + 272 (NSSQLCore.m:2946)
25  CoreData                      	0x00000001a460a0f8 __65-[NSPersistentStoreCoordinator executeRequest:withContext:error:]_block_invoke.547 + 8988 (NSPersistentStoreCoordinator.m:2995)
26  CoreData                      	0x00000001a45d6660 -[NSPersistentStoreCoordinator _routeHeavyweightBlock:] + 264 (NSPersistentStoreCoordinator.m:668)
27  CoreData                      	0x00000001a45ded28 -[NSPersistentStoreCoordinator executeRequest:withContext:error:] + 1200 (NSPersistentStoreCoordinator.m:2810)
28  CoreData                      	0x00000001a4655988 -[NSManagedObjectContext save:] + 984 (NSManagedObjectContext.m:1593)
29  CoreData                      	0x00000001a46f47dc __52+[NSCKEvent beginEventForRequest:withMonitor:error:]_block_invoke_2 + 352 (NSCKEvent.m:76)
30  CoreData                      	0x00000001a45c28f0 developerSubmittedBlockToNSManagedObjectContextPerform + 476 (NSManagedObjectContext.m:3984)
31  libdispatch.dylib             	0x00000001a4357fa8 _dispatch_client_callout + 20 (object.m:576)
32  libdispatch.dylib             	0x00000001a43677fc _dispatch_lane_barrier_sync_invoke_and_complete + 56 (queue.c:1104)
33  CoreData                      	0x00000001a4615c34 -[NSManagedObjectContext performBlockAndWait:] + 308 (NSManagedObjectContext.m:4108)
34  CoreData                      	0x00000001a46f45ac __52+[NSCKEvent beginEventForRequest:withMonitor:error:]_block_invoke + 192 (NSCKEvent.m:66)
35  CoreData                      	0x00000001a4825e68 -[PFCloudKitStoreMonitor performBlock:] + 92 (PFCloudKitStoreMonitor.m:148)
36  CoreData                      	0x00000001a46f4394 +[NSCKEvent beginEventForRequest:withMonitor:error:] + 256 (NSCKEvent.m:61)
37  CoreData                      	0x00000001a47cc6ec __57-[NSCloudKitMirroringDelegate _performExportWithRequest:]_block_invoke + 260 (NSCloudKitMirroringDelegate.m:1433)
38  CoreData                      	0x00000001a47c9970 __92-[NSCloudKitMirroringDelegate _openTransactionWithLabel:assertionLabel:andExecuteWorkBlock:]_block_invoke + 72 (NSCloudKitMirroringDelegate.m:957)
39  libdispatch.dylib             	0x00000001a4356248 _dispatch_call_block_and_release + 32 (init.c:1549)
40  libdispatch.dylib             	0x00000001a4357fa8 _dispatch_client_callout + 20 (object.m:576)
41  libdispatch.dylib             	0x00000001a435f5cc _dispatch_lane_serial_drain + 768 (queue.c:3934)
42  libdispatch.dylib             	0x00000001a4360158 _dispatch_lane_invoke + 432 (queue.c:4025)
43  libdispatch.dylib             	0x00000001a436b38c _dispatch_root_queue_drain_deferred_wlh + 288 (queue.c:7193)
44  libdispatch.dylib             	0x00000001a436abd8 _dispatch_workloop_worker_thread + 540 (queue.c:6787)
45  libsystem_pthread.dylib       	0x0000000227213680 _pthread_wqthread + 288 (pthread.c:2696)
46  libsystem_pthread.dylib       	0x0000000227211474 start_wqthread + 8 (:-1)

A 0xdead10cc crash is triggered when the system is suspending an app (because it is running out of the background execution time) while the app is holding a file lock or SQLite database lock at the moment. You can see more discussion in the "EXC_CRASH (SIGKILL)" section in Understanding the exception types in a crash report and the 0xdead10cc prevention post, which my colleagues Kevin and Quinn got involved.

Your app can run in the background in the following scenarios:

  • A user runs your app, and then returns to the home screen or switches to the other app.
  • A source, like the location service or VOIP, launches or resumes your app in the background. What source is relevant depends on the background modes your app supports.

In both cases, the system gives your app a short period of time before suspending it. If the tasks your app does when running in the background are light, the time window is long enough.

If your app needs to do long-time tasks in the time window, you might consider the following strategy:

  1. Figure out the long-time tasks at higher level, and separate them into some subtasks that are small enough so the task is cancellable.

  2. When you need to do a long-time task, start with calling beginBackgroundTask(expirationHandler:), with an appropriate expirationHandler. In an extension, the counterpart is performExpiringActivity(withReason:using:).

  3. Trigger the task.

  4. After the task is done, call endBackgroundTask() to end the background task.

In the case where your long-time task isn't finished before the system trying to suspend your app, the system calls the expirationHandler provided at step 2, and gives your app several seconds to clean up. An “appropriate" expirationHandler in this case follows this flow:

a. Cancel the long-time task. The task may be on a subtask at the moment, and you can wait until the current subtask is done. In case the subtask is small enough, the time window given to expirationHandler is long enough.

b. Call endBackgroundTask() to end the background task.

With that, a long-time task is either done or cancelled in a managed way before your app being suspended, which should avoid the termination you are hitting.

Best,
——
Ziqiao Chen
 Worldwide Developer Relations.

@DTS Engineer this doesn't actually answer my questions though. I understand that the app is crashing because of a deadlock in CoreData, but as I mentioned I’m not doing any long running tasks. There have been instances where I’m not doing any work, other than just opening the application and then it crashes in the background. The "long running task" you reference has to be coming from the CloudKit integration with CoreData. Thats what I’m asking for a solution to. How do I prevent that from crashing the application, as CloudKit is internally managed.

Oh, if it is Core Data + CloudKit triggers the long-time tasks, which lead to the crashes, it will be a framework bug, which I don't see anything you can do to work around. I can only suggest that you file a feedback report for the Core Data team to investigate – If you do so, please share your report ID here for folks to track.

Best,
——
Ziqiao Chen
 Worldwide Developer Relations.

CoreData/CloudKit 0xdead10cc
 
 
Q