App Crash triggered from background

Our application seems to be crashing due to an exc_bad_access
, and CouchbaseLiteSwift shows up in the stack trace.

Some context: This only appears to happen while the app is backgrounded, and usually hours after the app has been backgrounded. We are not sure what is triggering the code execution.
Is one of the solutions to close the database once the app enters the background ?

CouchbaseLite-Swift-Enterprise: 3.1.7
Exception Type: EXC_BAD_ACCESS
Exception Subtype: KERN_MEMORY_ERROR

EXC_BAD_ACCESS: Attempted to dereference garbage pointer 0x10c3ec010.

0  CouchbaseLiteSwift +0x1b2ec0    walIndexTryHdr (sqlite3-see-cccrypt.c:66805:3)
1  CouchbaseLiteSwift +0x1b2888    walIndexReadHdr (sqlite3-see-cccrypt.c)
2  CouchbaseLiteSwift +0x1b1fdc    walTryBeginRead (sqlite3-see-cccrypt.c:67214:12)
3  CouchbaseLiteSwift +0x1c79a8    walBeginReadTransaction (sqlite3-see-cccrypt.c:67520:10)
4  CouchbaseLiteSwift +0x1c74a8    lockBtree (sqlite3-see-cccrypt.c:73007:8)
5  CouchbaseLiteSwift +0x1c071c    sqlite3VdbeExec (sqlite3-see-cccrypt.c:96070:10)
6  CouchbaseLiteSwift +0x1bec48    sqlite3Step (sqlite3-see-cccrypt.c:90212:10)
7  CouchbaseLiteSwift +0x165f60    SQLite::Statement::executeStep() (Statement.cpp)
8  CouchbaseLiteSwift +0x1500a4    litecore::SQLiteKeyStore::read(litecore::Record&, litecore::ReadBy, litecore::ContentOption) const (SQLiteKeyStore.cc:306:19)
9  CouchbaseLiteSwift +0x10a7cc    litecore::KeyStore::get(fleece::slice, litecore::ContentOption) const (KeyStore.cc:58:9)
10 CouchbaseLiteSwift +0xfde70     litecore::DocumentKeys::read() (DocumentKeys.hh:33:34)
11 CouchbaseLiteSwift +0x23fbb8    fleece::impl::PersistentSharedKeys::transactionBegan() (SharedKeys.cc:255:9)
12 CouchbaseLiteSwift +0xfe888     litecore::ExclusiveTransaction::ExclusiveTransaction(litecore::DataFile*, bool) (DataFile.cc:472:17)
13 CouchbaseLiteSwift +0x1480e4    litecore::BackgroundDB::useInTransaction(fleece::slice, fleece::function_ref<bool (litecore::KeyStore&, litecore::SequenceTracker*)>)::$_2::operator()(litecore::DataFile*) const (BackgroundDB.cc:69:34)
14 CouchbaseLiteSwift +0x110b74    litecore::Housekeeper::_doExpiration() (Housekeeper.cc:115:16)
15 CouchbaseLiteSwift +0xfa05c     litecore::actor::GCDMailbox::safelyCall(void ( block_pointer)()) const (GCDMailbox.cc:81:13)
16 CouchbaseLiteSwift +0xfa118     ___ZN8litecore5actor10GCDMailbox7enqueueEPKcU13block_pointerFvvE_block_invoke (GCDMailbox.cc:108)
17 libdispatch.dylib +0x2244       __dispatch_call_block_and_release
18 libdispatch.dylib +0x3fa4       __dispatch_client_callout
19 libdispatch.dylib +0xb5c8       __dispatch_lane_serial_drain
20 libdispatch.dylib +0xc120       __dispatch_lane_invoke
21 libdispatch.dylib +0x17388      __dispatch_root_queue_drain_deferred_wlh
22 libdispatch.dylib +0x16bd4      __dispatch_workloop_worker_thread
23 libsystem_pthread.dylib +0x367c __pthread_wqthread

The fact that the crash occurs hours after the app is backgrounded suggests that the GCD sequence is being triggered by a system event, such as background fetch or a remote notification. But not sure what exactly.

For completeness, here is the state of all the threads:

Thread 0 - (TH_STATE_WAITING)
0  libsystem_kernel.dylib +0x1784 _mach_msg2_trap
1  libsystem_kernel.dylib +0x4e94 _mach_msg2_internal
2  libsystem_kernel.dylib +0x4dac _mach_msg_overwrite
3  libsystem_kernel.dylib +0x4bf8 _mach_msg
4  CoreFoundation +0x76800        ___CFRunLoopServiceMachPort
5  CoreFoundation +0x75eac        ___CFRunLoopRun
6  CoreFoundation +0xc8280        _CFRunLoopRunSpecific
7  GraphicsServices +0x14bc       _GSEventRunModal
8  UIKitCore +0x3ee670            -[UIApplication _run]
9  UIKitCore +0x14e84             _UIApplicationMain
10 KeepSafe +0x36fa0              main (main.swift:31:1)
11 dyld +0x2fde4                  start

Thread 1 - (TH_STATE_WAITING)
0  libsystem_kernel.dylib +0x708c  ___psynch_cvwait
1  libsystem_pthread.dylib +0x3f94 __pthread_cond_wait
2  KeepSafe +0xbbab78              Manager.wait(_:) (WebSocket.swift:1626:16)
3  KeepSafe +0xbc01f8              partial apply for closure #1 in Manager.init() (WebSocket.swift:1598:30)
4  KeepSafe +0xf6c60               thunk for @escaping @callee_guaranteed @Sendable () -> () (<compiler-generated>)
5  libdispatch.dylib +0x2244       __dispatch_call_block_and_release
6  libdispatch.dylib +0x3fa4       __dispatch_client_callout
7  libdispatch.dylib +0xb5c8       __dispatch_lane_serial_drain
8  libdispatch.dylib +0xc120       __dispatch_lane_invoke
9  libdispatch.dylib +0x17388      __dispatch_root_queue_drain_deferred_wlh
10 libdispatch.dylib +0x16bd4      __dispatch_workloop_worker_thread
11 libsystem_pthread.dylib +0x367c __pthread_wqthread

Thread 2 - (TH_STATE_WAITING)
0  CouchbaseLiteSwift +0x1b2ec0    walIndexTryHdr (sqlite3-see-cccrypt.c:66805:3)
1  CouchbaseLiteSwift +0x1b2888    walIndexReadHdr (sqlite3-see-cccrypt.c)
2  CouchbaseLiteSwift +0x1b1fdc    walTryBeginRead (sqlite3-see-cccrypt.c:67214:12)
3  CouchbaseLiteSwift +0x1c79a8    walBeginReadTransaction (sqlite3-see-cccrypt.c:67520:10)
4  CouchbaseLiteSwift +0x1c74a8    lockBtree (sqlite3-see-cccrypt.c:73007:8)
5  CouchbaseLiteSwift +0x1c071c    sqlite3VdbeExec (sqlite3-see-cccrypt.c:96070:10)
6  CouchbaseLiteSwift +0x1bec48    sqlite3Step (sqlite3-see-cccrypt.c:90212:10)
7  CouchbaseLiteSwift +0x165f60    SQLite::Statement::executeStep() (Statement.cpp)
8  CouchbaseLiteSwift +0x1500a4    litecore::SQLiteKeyStore::read(litecore::Record&, litecore::ReadBy, litecore::ContentOption) const (SQLiteKeyStore.cc:306:19)
9  CouchbaseLiteSwift +0x10a7cc    litecore::KeyStore::get(fleece::slice, litecore::ContentOption) const (KeyStore.cc:58:9)
10 CouchbaseLiteSwift +0xfde70     litecore::DocumentKeys::read() (DocumentKeys.hh:33:34)
11 CouchbaseLiteSwift +0x23fbb8    fleece::impl::PersistentSharedKeys::transactionBegan() (SharedKeys.cc:255:9)
12 CouchbaseLiteSwift +0xfe888     litecore::ExclusiveTransaction::ExclusiveTransaction(litecore::DataFile*, bool) (DataFile.cc:472:17)
13 CouchbaseLiteSwift +0x1480e4    litecore::BackgroundDB::useInTransaction(fleece::slice, fleece::function_ref<bool (litecore::KeyStore&, litecore::SequenceTracker*)>)::$_2::operator()(litecore::DataFile*) const (BackgroundDB.cc:69:34)
14 CouchbaseLiteSwift +0x110b74    litecore::Housekeeper::_doExpiration() (Housekeeper.cc:115:16)
15 CouchbaseLiteSwift +0xfa05c     litecore::actor::GCDMailbox::safelyCall(void ( block_pointer)()) const (GCDMailbox.cc:81:13)
16 CouchbaseLiteSwift +0xfa118     ___ZN8litecore5actor10GCDMailbox7enqueueEPKcU13block_pointerFvvE_block_invoke (GCDMailbox.cc:108)
17 libdispatch.dylib +0x2244       __dispatch_call_block_and_release
18 libdispatch.dylib +0x3fa4       __dispatch_client_callout
19 libdispatch.dylib +0xb5c8       __dispatch_lane_serial_drain
20 libdispatch.dylib +0xc120       __dispatch_lane_invoke
21 libdispatch.dylib +0x17388      __dispatch_root_queue_drain_deferred_wlh
22 libdispatch.dylib +0x16bd4      __dispatch_workloop_worker_thread
23 libsystem_pthread.dylib +0x367c __pthread_wqthread

Thread 3 - (TH_STATE_WAITING)
0  libsystem_kernel.dylib +0x1784  _mach_msg2_trap
1  libsystem_kernel.dylib +0x4e94  _mach_msg2_internal
2  libsystem_kernel.dylib +0x4dac  _mach_msg_overwrite
3  libsystem_kernel.dylib +0x4bf8  _mach_msg
4  CoreFoundation +0x76800         ___CFRunLoopServiceMachPort
5  CoreFoundation +0x75eac         ___CFRunLoopRun
6  CoreFoundation +0xc8280         _CFRunLoopRunSpecific
7  Foundation +0x2a0e4             -[NSRunLoop(NSRunLoop) runMode:beforeDate:]
8  Foundation +0x186bac            -[NSRunLoop(NSRunLoop) runUntilDate:]
9  UIKitCore +0x481a74             -[UIEventFetcher threadMain]
10 Foundation +0x115f2c            ___NSThread__start__
11 libsystem_pthread.dylib +0x17cc __pthread_start

Thread 4 - (TH_STATE_WAITING)
0 libsystem_kernel.dylib +0x708c  ___psynch_cvwait
1 libsystem_pthread.dylib +0x3f94 __pthread_cond_wait
2 libc++.1.dylib +0x21580         std::__1::condition_variable::wait(std::__1::unique_lock<std::__1::mutex>&)
3 ObjectiveRocks +0x1523f8        rocksdb::ThreadPoolImpl::Impl::BGThread(unsigned long)
4 ObjectiveRocks +0x152630        rocksdb::ThreadPoolImpl::Impl::BGThreadWrapper(void*)
5 ObjectiveRocks +0x153c00        void* std::__1::__thread_proxy<std::__1::tuple<std::__1::unique_ptr<std::__1::__thread_struct, std::__1::default_delete<std::__1::__thread_struct> >, void* (*)(void*), rocksdb::BGThreadMetadata*> >(void*)
6 libsystem_pthread.dylib +0x17cc __pthread_start

Thread 5 - (TH_STATE_WAITING)
0 libsystem_kernel.dylib +0x708c  ___psynch_cvwait
1 libsystem_pthread.dylib +0x3f94 __pthread_cond_wait
2 libc++.1.dylib +0x21580         std::__1::condition_variable::wait(std::__1::unique_lock<std::__1::mutex>&)
3 ObjectiveRocks +0x1523f8        rocksdb::ThreadPoolImpl::Impl::BGThread(unsigned long)
4 ObjectiveRocks +0x152630        rocksdb::ThreadPoolImpl::Impl::BGThreadWrapper(void*)
5 ObjectiveRocks +0x153c00        void* std::__1::__thread_proxy<std::__1::tuple<std::__1::unique_ptr<std::__1::__thread_struct, std::__1::default_delete<std::__1::__thread_struct> >, void* (*)(void*), rocksdb::BGThreadMetadata*> >(void*)
6 libsystem_pthread.dylib +0x17cc __pthread_start

Thread 6 - (TH_STATE_WAITING)
0 libsystem_kernel.dylib +0x1784  _mach_msg2_trap
1 libsystem_kernel.dylib +0x4e94  _mach_msg2_internal
2 libsystem_kernel.dylib +0x4dac  _mach_msg_overwrite
3 libsystem_kernel.dylib +0x4bf8  _mach_msg
4 KeepSafe +0xa28438              ksmachexc_i_handleExceptions (BSG_KSCrashSentry_MachException.c:229:36)
5 libsystem_pthread.dylib +0x17cc __pthread_start

Thread 7 - KSCrash Exception Handler (Primary) - (TH_STATE_RUNNING)
0 unknown file +0x0 unknown method

Thread 8 - (TH_STATE_WAITING)
0 libsystem_kernel.dylib +0x1700  _semaphore_wait_trap
1 libdispatch.dylib +0x4540       __dispatch_sema4_wait
2 libdispatch.dylib +0x4bf4       __dispatch_semaphore_wait_slow
3 KeepSafe +0xa2d93c              -[BSGAppHangDetector detectAppHangs] (BSGAppHangDetector.m:126:17)
4 KeepSafe +0xa2d8bc              DetectAppHangs (BSGAppHangDetector.m:216:5)
5 libsystem_pthread.dylib +0x17cc __pthread_start

Thread 9 - (TH_STATE_WAITING)
0 libsystem_kernel.dylib +0x150c  ___workq_kernreturn
1 libsystem_pthread.dylib +0x36c8 __pthread_wqthread

Thread 10 - (TH_STATE_WAITING)
0 libsystem_kernel.dylib +0x150c  ___workq_kernreturn
1 libsystem_pthread.dylib +0x36c8 __pthread_wqthread

Thread 11 - (TH_STATE_WAITING)
0 libsystem_kernel.dylib +0x1784  _mach_msg2_trap
1 libsystem_kernel.dylib +0x4e94  _mach_msg2_internal
2 libsystem_kernel.dylib +0x4dac  _mach_msg_overwrite
3 libsystem_kernel.dylib +0x4bf8  _mach_msg
4 CoreFoundation +0x76800         ___CFRunLoopServiceMachPort
5 CoreFoundation +0x75eac         ___CFRunLoopRun
6 CoreFoundation +0xc8280         _CFRunLoopRunSpecific
7 CFNetwork +0xf1c48              +[__CFN_CoreSchedulingSetRunnable _run:]
8 Foundation +0x115f2c            ___NSThread__start__
9 libsystem_pthread.dylib +0x17cc __pthread_start

Thread 12 - (TH_STATE_WAITING)
0 libsystem_kernel.dylib +0x1784  _mach_msg2_trap
1 libsystem_kernel.dylib +0x4e94  _mach_msg2_internal
2 libsystem_kernel.dylib +0x4dac  _mach_msg_overwrite
3 libsystem_kernel.dylib +0x4bf8  _mach_msg
4 CoreFoundation +0x76800         ___CFRunLoopServiceMachPort
5 CoreFoundation +0x75eac         ___CFRunLoopRun
6 CoreFoundation +0xc8280         _CFRunLoopRunSpecific
7 CoreFoundation +0xdb820         _CFRunLoopRun
8 CoreMotion +0xf94c              0x1902ed94c (0x1902ed444 + 1288)
9 libsystem_pthread.dylib +0x17cc __pthread_start

Thread 13 - (TH_STATE_WAITING)
0 libsystem_kernel.dylib +0x708c  ___psynch_cvwait
1 libsystem_pthread.dylib +0x3f94 __pthread_cond_wait
2 libc++.1.dylib +0x21580         std::__1::condition_variable::wait(std::__1::unique_lock<std::__1::mutex>&)
3 CouchbaseLiteSwift +0x14e7f4    litecore::actor::Timer::Manager::run() (Timer.cc:40:28)
4 CouchbaseLiteSwift +0x14e760    litecore::actor::Timer::Manager::Manager()::$_0::operator()() const (Timer.cc:28:24)
5 CouchbaseLiteSwift +0x14e754    decltype ((static_cast<litecore::actor::Timer::Manager::Manager()::$_0>({parm#1}))()) std::__1::__invoke<litecore::actor::Timer::Manager::Manager()::$_0>(litecore::actor::Timer::Manager::Manager()::$_0&&) (type_traits:3918:1)
6 CouchbaseLiteSwift +0x14e6e0    void std::__1::__thread_execute<std::__1::unique_ptr<std::__1::__thread_struct, std::__1::default_delete<std::__1::__thread_struct> >, litecore::actor::Timer::Manager::Manager()::$_0>(std::__1::tuple<std::__1::unique_ptr<std::__1::__thread_struct, std::__1::default_delete<std::__1::__thread_struct> >, litecore::actor::Timer::Manager::Manager()::$_0>&, std::__1::__tuple_indices<>) (thread:287:5)
7 libsystem_pthread.dylib +0x17cc __pthread_start

Thread 14 - (TH_STATE_WAITING)
0 libsystem_kernel.dylib +0x1784  _mach_msg2_trap
1 libsystem_kernel.dylib +0x4e94  _mach_msg2_internal
2 libsystem_kernel.dylib +0x4dac  _mach_msg_overwrite
3 libsystem_kernel.dylib +0x4bf8  _mach_msg
4 CoreFoundation +0x76800         ___CFRunLoopServiceMachPort
5 CoreFoundation +0x75eac         ___CFRunLoopRun
6 CoreFoundation +0xc8280         _CFRunLoopRunSpecific
7 CoreFoundation +0xda510         __legacyStreamRunLoop_workThread
8 libsystem_pthread.dylib +0x17cc __pthread_start

Thread 15 - (TH_STATE_WAITING)
0 libsystem_kernel.dylib +0x150c  ___workq_kernreturn
1 libsystem_pthread.dylib +0x36c8 __pthread_wqthread

Thread 16 - (TH_STATE_WAITING)
0 libsystem_kernel.dylib +0x9330  _select$DARWIN_EXTSN
1 CoreFoundation +0x1484b0        ___CFSocketManager
2 libsystem_pthread.dylib +0x17cc __pthread_start

Thread 17 - (TH_STATE_WAITING)
0 libsystem_kernel.dylib +0x150c  ___workq_kernreturn
1 libsystem_pthread.dylib +0x36c8 __pthread_wqthread

Thread 18 - (TH_STATE_RUNNING)
0 libsystem_pthread.dylib +0x1468 _start_wqthread

Thread 19 - (TH_STATE_WAITING)
0 libsystem_kernel.dylib +0x150c  ___workq_kernreturn
1 libsystem_pthread.dylib +0x36c8 __pthread_wqthread

Thread 20 - (TH_STATE_WAITING)
0 libsystem_kernel.dylib +0x150c  ___workq_kernreturn
1 libsystem_pthread.dylib +0x36c8 __pthread_wqthread

Thread 21 - (TH_STATE_WAITING)
0 libsystem_kernel.dylib +0x150c  ___workq_kernreturn
1 libsystem_pthread.dylib +0x36c8 __pthread_wqthread

Thread 22 - (TH_STATE_WAITING)
0 libsystem_kernel.dylib +0x150c  ___workq_kernreturn
1 libsystem_pthread.dylib +0x36c8 __pthread_wqthread

Thread 23 - (TH_STATE_WAITING)
0 libsystem_kernel.dylib +0x150c  ___workq_kernreturn
1 libsystem_pthread.dylib +0x36c8 __pthread_wqthread

Thread 24 - (TH_STATE_WAITING)
0 libsystem_kernel.dylib +0x1718  _semaphore_timedwait_trap
1 libdispatch.dylib +0x45bc       __dispatch_sema4_timedwait
2 libdispatch.dylib +0x4bbc       __dispatch_semaphore_wait_slow
3 libdispatch.dylib +0x15c90      __dispatch_worker_thread
4 libsystem_pthread.dylib +0x17cc __pthread_start

Thread 25 - (TH_STATE_WAITING)
0 libsystem_kernel.dylib +0x1718  _semaphore_timedwait_trap
1 libdispatch.dylib +0x45bc       __dispatch_sema4_timedwait
2 libdispatch.dylib +0x4bbc       __dispatch_semaphore_wait_slow
3 libdispatch.dylib +0x15c90      __dispatch_worker_thread
4 libsystem_pthread.dylib +0x17cc __pthread_start

Thread 26 - (TH_STATE_WAITING)
0 libsystem_kernel.dylib +0x708c  ___psynch_cvwait
1 libsystem_pthread.dylib +0x3f94 __pthread_cond_wait
2 JavaScriptCore +0xfc6e0         <redacted>
3 libsystem_pthread.dylib +0x17cc __pthread_start

Thread 27 - (TH_STATE_WAITING)
0 libsystem_kernel.dylib +0x150c  ___workq_kernreturn
1 libsystem_pthread.dylib +0x36c8 __pthread_wqthread

Thread 28 - (TH_STATE_WAITING)
0 libsystem_kernel.dylib +0x150c  ___workq_kernreturn
1 libsystem_pthread.dylib +0x36c8 __pthread_wqthread
1 Like

The call to litecore::Housekeeper::_doExpiration() indicates that it’s expiring a document because its expiration time was reached.

Doing file I/O while an app is in the background is fraught with peril, because when the device is locked the app may lose access to the filesystem; depending on how you’ve configured its background modes (I can’t remember the specific API name, it’s been too long, sorry!)

It’s weird that this causes a crash and not just an I/O error from SQLite … but after looking at walIndexTryHdr() in SQLite I think I know what’s going on. This function reads the -shm file that exists while a DB is open. It’s a memory-mapped file so it just reads data out of it using memcpy. But reading mapped memory while the backing file is unreadable will cause a segfault.

The solution to this is to close all databases before the filesystem gets locked away, and then reopen them when unlocked. There are OS notifications you can listen for that tell you when this happens.

If you want to trigger this sooner/more reliably, create a document and set its expiration time for a few minutes in the future, then lock the device and wait.

2 Likes

Thank You jens! We were able to reproduce quickly with your suggestion.:person_bowing: