Uploaded image for project: 'Realm Cocoa SDK'
  1. Realm Cocoa SDK
  2. RCOCOA-800

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

    • Type: Icon: Bug Bug
    • Resolution: Fixed
    • Priority: Icon: Critical - P2 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 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

            Assignee:
            finn.schiermer-andersen@mongodb.com Finn Andersen (Inactive)
            Reporter:
            unitosyncbot Unito Sync Bot
            Votes:
            0 Vote for this issue
            Watchers:
            1 Start watching this issue

              Created:
              Updated:
              Resolved: