Crash while compaction in background on iOS
using couchbase-lite-ios 1.4 (via pod install)
The following crash occurs rather frequently when database compaction starts while app is started in background (e.g. via background fetch or silent push message) Compaction is started automatically, not manually.
Crashed: Thread
0 PurpleAnt 0x1004d2894 std::__1::__hash_const_iterator<std::__1::__hash_node<std::__1::__hash_value_type<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, bool>, void*>*> std::__1::__hash_table<std::__1::__hash_value_type<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, bool>, std::__1::__unordered_map_hasher<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::__hash_value_type<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, bool>, std::__1::hash<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >, true>, std::__1::__unordered_map_equal<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::__hash_value_type<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, bool>, std::__1::equal_to<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >, true>, std::__1::allocator<std::__1::__hash_value_type<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, bool> > >::find<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&) const (__hash_table:2228)
1 PurpleAnt 0x1004d133c cbforest::Database::getKeyStore(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >) const (unordered_map:1121)
2 PurpleAnt 0x1004d19e8 cbforest::Database::updatePurgeCount() (Database.cc:227)
3 PurpleAnt 0x1004d10b4 cbforest::Database::compactionCallback(_fdb_file_handle*, unsigned int, char const*, fdb_doc_struct*, unsigned long long, unsigned long long, void*) (Database.cc:406)
4 PurpleAnt 0x100516d78 _fdb_compact_file(_fdb_kvs_handle*, filemgr*, btreeblk_handle*, docio_handle*, hbtrie*, hbtrie*, btree*, btree*, unsigned long long, bool) + 8200
5 PurpleAnt 0x1005154c4 fdb_compact_file + 1876
6 PurpleAnt 0x100501624 compactor_thread(void*) + 22196
7 libsystem_pthread.dylib 0x18a3e568c _pthread_body + 240
8 libsystem_pthread.dylib 0x18a3e559c _pthread_body + 282
9 libsystem_pthread.dylib 0x18a3e2cb4 thread_start + 4
ForestDB is calling the compaction callback from the background compactor thread, and unfortunately Database::compactionCallback calls updatePurgeCount() which isn't thread-safe.
The real fix won't be simple, because the Database class isn't designed to be thread-safe, and CBForest itself has no notion of queues or event loops so it can't somehow schedule the updatePurgeCount() call to run on the regular thread.
The best workaround I can think of is to take out the call to updatePurgeCount() at Database.cc:406. If your app never purges documents, there won't be any side effects. If it does purge documents, you'll need to rebuild view indexes after purging (which is what that updatePurgeCount call would have done for you.)