I recently added SwiftData to my project in a limited capacity. I'm creating ModelConfiguration -> ModelContext directly in Swift code rather than in SwiftUI. I'm using an app group & a CloudKit database/container.
The functionality all seems fine, but I'm dealing with random 0xdead10cc crashes from threads with CoreData/libsqlite3.dylib in the stack traces (particularly with widgets & complications which aren't actively writing anything), often with NSCloudKitMirroringDelegate.m also in the stack. I haven't seen any actual functionality issues, but the crashing is worrisome.
I understand they're keeping files open to cause the 0xdead10cc, but my question is: Is there a clean way to shut down or force shut down SwiftData when using CloudKit? I've looked through example code on Apple's Developer site, but I can't seem to find anything about cleanup/shutdown best practices, though I may be missing something.
Here's an example thread from a crash log:
Thread 12:
0 libsystem_kernel.dylib 0x00000000258b4fe4 pread + 12
1 libsqlite3.dylib 0x0000000023ce7684 seekAndRead + 88 (sqlite3.c:44032)
2 libsqlite3.dylib 0x0000000023c5ffc4 unixRead + 200 (sqlite3.c:44124)
3 libsqlite3.dylib 0x0000000023c730fc readDbPage + 132 (sqlite3.c:66901)
4 libsqlite3.dylib 0x0000000023cf14e4 getPageNormal + 532 (sqlite3.c:69515)
5 libsqlite3.dylib 0x0000000023cfd684 getAndInitPage + 104 (sqlite3.c:79184)
6 libsqlite3.dylib 0x0000000023c8f99c moveToRoot + 532 (sqlite3.c:82309)
7 libsqlite3.dylib 0x0000000023cfa448 sqlite3BtreeTableMoveto + 168 (sqlite3.c:82547)
8 libsqlite3.dylib 0x0000000023c859fc sqlite3VdbeExec + 4996 (sqlite3.c:105391)
9 libsqlite3.dylib 0x0000000023c83da4 sqlite3_step + 976 (sqlite3.c:97868)
10 CoreData 0x00000000211c92d4 _execute + 128 (NSSQLiteConnection.m:4573)
11 CoreData 0x00000000211c5e74 -[NSSQLiteConnection execute] + 1784 (NSSQLiteConnection.m:5014)
12 CoreData 0x000000002121c3f8 -[NSSQLiteConnection insertRow:] + 1488 (NSSQLiteConnection.m:3608)
13 CoreData 0x00000000211ca160 _executeSaveChangesRequest + 1792 (NSSQLCore_Functions.m:2543)
14 CoreData 0x00000000211dc128 -[NSSQLSaveChangesRequestContext executeRequestCore:] + 28 (NSSQLSaveChangesRequestContext.m:263)
15 CoreData 0x00000000211fa424 -[NSSQLStoreRequestContext executeRequestUsingConnection:] + 220 (NSSQLStoreRequestContext.m:183)
16 CoreData 0x00000000211cce3c __52-[NSSQLDefaultConnectionManager handleStoreRequest:]_block_invoke + 56 (NSSQLConnectionManager.m:302)
17 CoreData 0x00000000211c99d4 __37-[NSSQLiteConnection performAndWait:]_block_invoke + 40 (NSSQLiteConnection.m:733)
18 libdispatch.dylib 0x0000000020af2b94 _dispatch_client_callout + 16 (object.m:576)
19 libdispatch.dylib 0x0000000020b004d8 _dispatch_lane_barrier_sync_invoke_and_complete + 56 (queue.c:1104)
20 CoreData 0x00000000211c3d4c -[NSSQLiteConnection performAndWait:] + 140 (NSSQLiteConnection.m:730)
21 CoreData 0x000000002122fb3c -[NSSQLDefaultConnectionManager handleStoreRequest:] + 208 (NSSQLConnectionManager.m:297)
22 CoreData 0x00000000211bd16c -[NSSQLCoreDispatchManager routeStoreRequest:] + 216 (NSSQLCoreDispatchManager.m:60)
23 CoreData 0x00000000211bfb8c -[NSSQLCore dispatchRequest:withRetries:] + 168 (NSSQLCore.m:3999)
24 CoreData 0x00000000211c0480 -[NSSQLCore executeRequest:withContext:error:] + 2044 (NSSQLCore.m:2963)
25 CoreData 0x000000002134662c __65-[NSPersistentStoreCoordinator executeRequest:withContext:error:]_block_invoke.387 + 8968 (NSPersistentStoreCoordinator.m:2967)
26 CoreData 0x00000000211c6190 -[NSPersistentStoreCoordinator _routeHeavyweightBlock:] + 220 (NSPersistentStoreCoordinator.m:644)
27 CoreData 0x00000000211bf3fc -[NSPersistentStoreCoordinator executeRequest:withContext:error:] + 1112 (NSPersistentStoreCoordinator.m:2779)
28 CoreData 0x00000000211d5468 -[NSManagedObjectContext save:] + 988 (NSManagedObjectContext.m:1624)
29 CoreData 0x0000000021296ba8 __52+[NSCKEvent beginEventForRequest:withMonitor:error:]_block_invoke_2 + 280 (NSCKEvent.m:76)
30 CoreData 0x00000000211d1024 developerSubmittedBlockToNSManagedObjectContextPerform + 156 (NSManagedObjectContext.m:3987)
31 libdispatch.dylib 0x0000000020af2b94 _dispatch_client_callout + 16 (object.m:576)
32 libdispatch.dylib 0x0000000020b004d8 _dispatch_lane_barrier_sync_invoke_and_complete + 56 (queue.c:1104)
33 CoreData 0x00000000211e3d8c -[NSManagedObjectContext performBlockAndWait:] + 256 (NSManagedObjectContext.m:4104)
34 CoreData 0x000000002129e14c __52+[NSCKEvent beginEventForRequest:withMonitor:error:]_block_invoke + 152 (NSCKEvent.m:66)
35 CoreData 0x00000000212231d0 -[PFCloudKitStoreMonitor performBlock:] + 84 (PFCloudKitStoreMonitor.m:148)
36 CoreData 0x0000000021284c28 +[NSCKEvent beginEventForRequest:withMonitor:error:] + 184 (NSCKEvent.m:61)
37 CoreData 0x000000002125fb80 __57-[NSCloudKitMirroringDelegate _performExportWithRequest:]_block_invoke + 256 (NSCloudKitMirroringDelegate.m:1435)
38 CoreData 0x0000000021209cb4 __92-[NSCloudKitMirroringDelegate _openTransactionWithLabel:assertionLabel:andExecuteWorkBlock:]_block_invoke + 64 (NSCloudKitMirroringDelegate.m:959)
39 libdispatch.dylib 0x0000000020af1288 _dispatch_call_block_and_release + 24 (init.c:1549)
40 libdispatch.dylib 0x0000000020af2b94 _dispatch_client_callout + 16 (object.m:576)
41 libdispatch.dylib 0x0000000020af96bc _dispatch_lane_serial_drain + 680 (queue.c:3934)
42 libdispatch.dylib 0x0000000020afa124 _dispatch_lane_invoke + 376 (queue.c:4025)
43 libdispatch.dylib 0x0000000020b03c40 _dispatch_root_queue_drain_deferred_wlh + 268 (queue.c:7193)
44 libdispatch.dylib 0x0000000020b034fc _dispatch_workloop_worker_thread + 516 (queue.c:6787)
45 libsystem_pthread.dylib 0x0000000025f9b7bc _pthread_wqthread + 280 (pthread.c:2696)
46 libsystem_pthread.dylib 0x0000000025f9b85c 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, and yet the app is holding a file lock or SQLite database lock at the moment.
Your app can run in the background in the following scenarios:
- The 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.
The 0xdead10cc prevention post provides more context about the kind of crash, though the solution may not directly apply if it is the synchronization activity of the framework triggering the crash.
Now to comment your questions:
I'm using an app group & a CloudKit database/container.
This configuration implies that multiple processes, such as your app and extensions, can synchronize the data store. If that is the case, it's probably not a great choice. For more information, see Avoid synchronizing a store with multiple persistent containers.
my question is: Is there a clean way to shut down or force shut down SwiftData when using CloudKit?
You can do that by nullifying the model container, and also other SwiftData objects such as model context(s) and models associated with the container because those objects may turn out hold a reference of the container.
Best,
——
Ziqiao Chen
Worldwide Developer Relations.