-
Type: Bug
-
Resolution: Fixed
-
Priority: Critical - P2
-
None
-
Affects Version/s: None
-
Component/s: None
<!---
Bugs: To help you as fast as possible with an issue please describe your issue
and the steps you have taken to reproduce it in as many details as possible.
-->
Goals
<!--- What do you want to achieve? -->
The app is loading data on a background thread from one local db to realm. I have it batching in units of 250 and looping in a function with autoreleasepool wrapped around it to try to keep the memory pressure down since I thought that was the issue first. Nothing seems to work.
Expected Results
Not to crash.
Actual Results
Crashed: com.apple.root.background-qos
SIGABRT ABORT 0x00000001b89c4df0
0
libsystem_kernel.dylib
__pthread_kill + 8
2
libsystem_c.dylib
abort + 104
3
Realm
realm::util::terminate(char const_, char const_, long) + 10
4
Realm
realm::util::terminate_internal(std::*1::basic_stringstream<char, std::*1::char_traits<char>, std::__1::allocator<char> >&) + 780
5
Realm
realm::util::terminate(char const_, char const_, long, std::initializer_list<realm::util::Printable>&&) + 328
6
Realm
realm::Cluster::init(realm::MemRef) + 156
7
Realm
realm::ClusterNodeInner::try_get(realm::ObjKey, realm::ClusterNode::State&) const + 204
8
Realm
realm::ClusterTree::is_valid(realm::ObjKey) const + 36
9
Realm
realm::ConstObj::is_valid() const + 108
10
Realm
RLMObject_Private.hpp - Line 41
RLMVerifyInWriteTransaction(RLMObjectBase*) + 41
11
Realm
RLMAccessor.mm - Line 78
invocation function for block in objc_object* (anonymous namespace)::makeSetter<bool, bool>(RLMProperty*) + 78
12
App
Sync.swift - Line 730
Sync.createRealmObjectFromObject(object:container:queryRealm + 730
13
App
Sync.swift - Line 225
closure #1 in closure #3 in Sync.updateRealmObjects(_ + 225
14
App
<compiler-generated> - Line 4335423344
partial apply for thunk for @callee_guaranteed () -> (@error @owned Error) + 4335423344
15
App
thunk for @callee_guaranteed () -> (@error @owned Error)partial apply + 4335500284
16
RealmSwift
Realm.swift - Line 227
Realm.write<A>(withoutNotifying:_ + 227
17
App
Sync.swift - Line 1958
closure #3 in Sync.updateRealmObjects(_ + 1958
18
App
<compiler-generated> - Line 4335423344
partial apply for thunk for @callee_guaranteed () -> (@error @owned Error) + 4335423344
19
App
thunk for @callee_guaranteed () -> (@error @owned Error)partial apply + 4335500264
20
libswiftObjectiveC.dylib
$s10ObjectiveC15autoreleasepool8invokingxxyKXE_tKlF + 64
21
App
Sync.swift - Line 205
Sync.updateRealmObjects(_ + 205
22
App
Sync.swift - Line 82
closure #1 in Sync.requestForAccess(_ + 82
23
App
<compiler-generated> - Line 4333817056
thunk for @escaping @callee_guaranteed () -> () + 4333817056
24
libdispatch.dylib
<redacted> + 32
29
libsystem_pthread.dylib
start_wqthread + 8
Steps for others to Reproduce
I cannot reproduce this error locally on any devices. I tried with large data sets on an iPhone 6s, iPhone XS Max, iPad Pro, iPhone 11. Yet I see it in the field. I've tried to break out the offending function which is mutating the object into sub functions to get a better stacktace, but that doesn't help. It is crashing on this createRealmObjectFromObject function.
Code Sample
func updateRealmObjects(){ DispatchQueue(label: "background").async { autoreleasepool { let writeRealm = try! Realm() do { let objects = getSomeObjectArray() var escape = false parentLoop: while objects!.count != 0 || escape { try autoreleasepool { try writeRealm.safeWrite { loop: while index <objectsCount { if (objects?.count ?? 0) > 0 { writeRealm.create(Object.self, value: self.createRealmObjectFromObject(object: objects![0], container: container, queryRealm: writeRealm), update: .modified) } else { print("THIS SHOULD NEVER HAPPEN.) escape = true break loop; } index += 1 objects!.remove(at: 0) if index%250 == 0{ index -= 250 objectCount -= 250 break loop; } } } } } } } catch { print(error) } } } func createRealmObjectFromObject(object: LocalObjectType, container: String, queryRealm: Realm) -> RealmObject { let syncObject = queryRealm.object(ofType: RealmObject.self, forPrimaryKey: object.identifier) ?? RealmObject() syncObject.property0 = object.property0 syncObject.property1 = object.property1 ... etc return syncObject }
(excuse the formatting/ hacky style here. Just was throwing stuff at the wall to fix production code that didn't fail in our testing )
Version of Realm and Tooling
Realm (5.3.3):
- Realm/Headers (= 5.3.3)
- Realm/Headers (5.3.3)
- RealmSwift (5.3.3):
- Realm (= 5.3.3)
Realm framework version: ?
- Realm (= 5.3.3)
Realm Object Server version: N/A
Xcode version: Version 11.6 (11E708)
iOS/OSX version:
13.6.0 (17G68) - iPhone 11 Pro
13.4.1 (17E262) - iPhone 7 Plus
13.6.1 (17G80) - iPhone 11 Pro Max
13.6.0 (17G68) - iPhone X
Dependency manager + version: irrelevant. Cocoapods.
Updates from users and crash reports
It looks like wrapping the code in autorelease, ensuring serialized background threads, etc have shifted the problem. Now it is crashing, but for less users. To reproduce the issue now— it works on launch the first time. The user kills the app. Relaunches it and the second time it crashes. From the updated crash reports for the latest version we are seeing the crash on the outer function where it tries to add what looks to be an invalidated object? to Realm.. That only happens after the app is killed and restarted.. At this point it feels like wack-a-mole:
RLMObjectBase.mm - Line 293
-[RLMObjectBase isInvalidated] + 293