realm-swift: Crash for some users Realm 5.3.3 - realm::util::terminate(char const*, char const*, long) + 10

Goals

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_listrealm::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(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 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

About this issue

  • Original URL
  • State: closed
  • Created 4 years ago
  • Reactions: 2
  • Comments: 19 (6 by maintainers)

Most upvoted comments

@gongzhang unfortunately I don’t have one. However we’ve noticed that if user is ā€œfortunedā€ to get this crash, then it will always crash for that user. So, we mark it and on the next launch completely delete Realm database. We can do it since it’s possible for us to sync all data once again from backend. Not a solution, but workaround that increases our crash-free.

@leemaguire actually this has become almost unusable on 5.3.5. Duplicate objects are being created. Linked Lists on the parent object are not reliably being added 😬 Not to mention it’s extremely slow now… UI Updates are being called on the main thread after write transactions complete on the background thread (which is awkward when you are batching data and things jump around visually during a sync).

Any chance for a migration tool to go back to the land of 4.x? We can also schedule a screen-share session and get to the bottom of it and hopefully help ya’ll out.