Uploaded image for project: 'Realm Core'
  1. Realm Core
  2. RCORE-1167

Assert while trimming history (2)

      Hi,

      I'm experiencing this crash with some users:

      0   libsystem_kernel.dylib        	0x00000001f1011b38 __pthread_kill + 8 (:-1)
      1   libsystem_pthread.dylib       	0x000000022a73e3bc pthread_kill + 268 (pthread.c:1668)
      2   libsystem_c.dylib             	0x00000001c46db524 abort + 168 (abort.c:118)
      3   Realm                         	0x000000010098ceb0 please_report_this_issue_in_github_realm_realm_core + 12
      4   Realm                         	0x000000010098d198 realm::util::terminate_internal(std::__1::basic_stringstream<char, std::__1::char_traits<char>, std::__1::allocator<char> >&) + 260
      5   Realm                         	0x000000010098d394 realm::util::terminate_with_info(char const*, char const*, long, char const*, std::initializer_list<realm::util::Printable>&&) + 388
      6   Realm                         	0x00000001007ed678 void realm::util::terminate_with_info<unsigned long&, unsigned long&, unsigned long const&, unsigned long&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >(c... + 136
      7   Realm                         	0x00000001007ed450 realm::SlabAlloc::do_free(unsigned long, char*) + 1740
      8   Realm                         	0x00000001007f5af4 realm::Array::destroy_deep(realm::MemRef, realm::Allocator&) + 64
      9   Realm                         	0x00000001007f1404 realm::Array::destroy_deep(unsigned long, realm::Allocator&) + 140
      10  Realm                         	0x00000001007fe460 realm::ArrayBinary::erase(unsigned long) + 68
      11  Realm                         	0x000000010084f94c realm::util::FunctionRef<unsigned long (realm::BPlusTreeNode*, unsigned long)>::FunctionRef<realm::BPlusTree<realm::BinaryData>::erase(unsigned long)::'lambda'(realm::BPlusTreeNode*, unsigned long)... + 28
      12  Realm                         	0x0000000100811504 realm::BPlusTreeBase::bptree_erase(unsigned long, realm::util::FunctionRef<unsigned long (realm::BPlusTreeNode*, unsigned long)>) + 52
      13  Realm                         	0x000000010084f7b8 (anonymous namespace)::InRealmHistory::set_oldest_bound_version(unsigned long long) + 164
      14  Realm                         	0x000000010082d610 realm::DB::low_level_commit(unsigned long long, realm::Transaction&, bool) + 296
      15  Realm                         	0x000000010082d3f4 realm::DB::do_commit(realm::Transaction&, bool) + 140
      16  Realm                         	0x0000000100966334 realm::Transaction::commit() + 80
      17  Realm                         	0x0000000100a7aadc realm::_impl::RealmCoordinator::open_db() + 1964
      18  Realm                         	0x0000000100a7b604 realm::_impl::RealmCoordinator::do_get_realm(realm::RealmConfig, std::__1::shared_ptr<realm::Realm>&, realm::util::Optional<realm::VersionID>, realm::util::CheckedUniqueLock&) + 72
      19  Realm                         	0x0000000100a7b450 realm::_impl::RealmCoordinator::get_realm(realm::RealmConfig, realm::util::Optional<realm::VersionID>) + 424
      20  Realm                         	0x0000000100afa220 realm::Realm::get_shared_realm(realm::RealmConfig) + 120
      21  Realm                         	0x00000001007be7a8 +[RLMRealm realmWithConfiguration:queue:error:] + 1116 (RLMRealm.mm:532)
      22  RealmSwift                    	0x0000000100e123a8 init + 40 (<compiler-generated>:0)
      23  RealmSwift                    	0x0000000100e123a8 init + 40 (<compiler-generated>:0)
      24  RealmSwift                    	0x0000000100e123a8 Realm.init(configuration:queue:) + 92 (Realm.swift:95)
      25  Geory                         	0x000000010008af3c closure #1 in closure #1 in initializeDatabase(qos:shouldMigrate:shouldCompact:completion:) + 724 (DatabaseManagement.swift:305)
      26  Geory                         	0x0000000100046350 thunk for @callee_guaranteed () -> (@error @owned Error) + 20 (<compiler-generated>:0)
      27  Geory                         	0x000000010008a9b4 partial apply for thunk for @callee_guaranteed () -> (@error @owned Error) + 16 (<compiler-generated>:0)
      28  Geory                         	0x0000000100090d90 thunk for @callee_guaranteed () -> (@error @owned Error)partial apply + 12
      29  libswiftObjectiveC.dylib      	0x00000001e80b7a10 autoreleasepool<A>(invoking:) + 64 (ObjectiveC.swift:172)
      30  Geory                         	0x0000000100090a74 partial apply for closure #1 in initializeDatabase(qos:shouldMigrate:shouldCompact:completion:) + 88 (DatabaseManagement.swift:94)
      31  Geory                         	0x000000010004605c thunk for @escaping @callee_guaranteed () -> () + 28 (<compiler-generated>:0)
      32  libdispatch.dylib             	0x00000001b923ae6c _dispatch_call_block_and_release + 32 (init.c:1517)
      33  libdispatch.dylib             	0x00000001b923ca30 _dispatch_client_callout + 20 (object.m:560)
      34  libdispatch.dylib             	0x00000001b924e280 _dispatch_root_queue_drain + 680 (inline_internal.h:2622)
      35  libdispatch.dylib             	0x00000001b924e96c _dispatch_worker_thread2 + 164 (queue.c:6935)
      36  libsystem_pthread.dylib       	0x000000022a738080 _pthread_wqthread + 228 (pthread.c:2612)
      37  libsystem_pthread.dylib       	0x000000022a737e5c start_wqthread + 8 (:-1)
      

      The method for initialization is as follows:

      func initializeDatabase(qos: DispatchQoS.QoSClass, shouldMigrate: Bool, shouldCompact: Bool, completion: @escaping () -> () = {}) {
          
          DispatchQueue.global(qos: qos).async {
              
              autoreleasepool {
                  
                  do {
                      
                      var realmConfiguration = Realm.Configuration()
                      
                      var compactStatus: String = "compacting has not been invoked"
                      
                      if shouldCompact {
                          
                          realmConfiguration.shouldCompactOnLaunch = { totalBytes, usedBytes in
                              
                              if totalBytes > ( 10 * 1024 * 1024) && Double(usedBytes) / Double(totalBytes) < 0.7 {
                                  
                                  compactStatus = "compacting was necessary (\(totalBytes.bytesString) total bytes with \(usedBytes.bytesString) bytes used, usage quota of \(String(format: "%.1f", Float(usedBytes)/Float(totalBytes)*100))%)"
                                  
                                  return true
                                  
                              }
                              
                              else {
                                  
                                  compactStatus = "compacting was not necessary (\(totalBytes.bytesString) total bytes with \(usedBytes.bytesString) bytes used, quota of \(String(format: "%.1f", Float(usedBytes)/Float(totalBytes)*100))%)"
                                  
                                  return false
                                  
                              }
                              
                          }
                          
                      }
                      
                      
                      if shouldMigrate {
                          
                          realmConfiguration.schemaVersion = realmSchemaVersion
                          
                          realmConfiguration.migrationBlock = { migration, oldSchemaVersion in
                              
                              if oldSchemaVersion < 4001 {
                                  
                                  migration.enumerateObjects(ofType: "GeoryLabelObject") { oldObject, newObject in
                                      
                                      guard let oldObject = oldObject else { return }
                                      
                                      let newLabelObject: MigrationObject = migration.create("LabelObject")
                                      
                                      newLabelObject["identifier"] = oldObject["identifier"] as? String ?? UUID().uuidString
                                      
                                      newLabelObject["geo_latitude"] = oldObject["latitude"] as? Double ?? 0
                                      newLabelObject["geo_longitude"] = oldObject["longitude"] as? Double ?? 0
                                      newLabelObject["geo_radius"] = oldObject["radius"] as? Double ?? georyCurrentConfiguration.preferenceLabelRadius
                                      
                                      newLabelObject["info_text"] = oldObject["text"] as? String ?? ""
                                      newLabelObject["info_icon"] = oldObject["iconName"] as? String ?? ""
                                      newLabelObject["info_placemark"] = ""
                                      
                                      if let oldColorData = oldObject["colorData"] as? List<Float>, oldColorData.count == 4 {
                                          
                                          newLabelObject["color_red"] = oldColorData[0]
                                          newLabelObject["color_green"] = oldColorData[1]
                                          newLabelObject["color_blue"] = oldColorData[2]
                                          newLabelObject["color_alpha"] = oldColorData[3]
                                          
                                      }
                                      
                                      if let newObject = newObject {
                                          
                                          migration.delete(newObject)
                                          
                                      }
                                          
                                  }
                                  
                                  migration.enumerateObjects(ofType: "GeoryLocationObject") { oldObject, newObject in
                                      
                                      guard let oldObject = oldObject else { return }
                                      
                                      if let isVisit = oldObject["isVisit"] as? Bool, isVisit {
                                          
                                          let newVisitObject = migration.create("VisitObject")
                                          
                                          newVisitObject["identifier"] = oldObject["identifier"] as? String ?? UUID().uuidString
                                          
                                          newVisitObject["geo_latitude"] = oldObject["geo_latitude"] as? Double ?? 0
                                          newVisitObject["geo_longitude"] = oldObject["geo_longitude"] as? Double ?? 0
                                          newVisitObject["geo_accuracy"] = oldObject["geo_accuracy"] as? Double ?? 0
                                          
                                          newVisitObject["ts_arrival"] = oldObject["ts_arrival"] as? Double ?? 0
                                          newVisitObject["ts_departure"] = oldObject["ts_departure"] as? Double ?? 0
                                          newVisitObject["ts_timezone"] = oldObject["ts_timezone"] as? String ?? TimeZone.autoupdatingCurrent.identifier
                                          
                                          newVisitObject["isHidden"] = oldObject["isHidden"] as? Bool ?? false
                                          newVisitObject["isFixed"] = oldObject["isFixed"] as? Bool ?? false
                                          newVisitObject["isEdited"] = oldObject["isCorrected"] as? Bool ?? false || oldObject["isManual"] as? Bool ?? false
                                          newVisitObject["isHighlight"] = false
                                          
                                          newVisitObject["info_rating"] = oldObject["info_rating"] as? Double ?? 0
                                          newVisitObject["info_notes"] = oldObject["info_notes"] as? String ?? ""
                                          newVisitObject["info_placemark"] = oldObject["info_placemark"] as? String ?? ""
                                          newVisitObject["info_transport"] = oldObject["info_transport"] as? Double ?? 0
                                          
                                          newVisitObject["weather_condition"] = oldObject["weather_condition"] as? Double ?? -999
                                          newVisitObject["weather_temperature"] = oldObject["weather_temperature"] as? Double ?? -999
                                          newVisitObject["weather_feels"] = oldObject["weather_feels"] as? Double ?? -999
                                          newVisitObject["weather_humidity"] = oldObject["weather_humidity"] as? Double ?? -999
                                          newVisitObject["weather_wind_speed"] = oldObject["weather_wind_speed"] as? Double ?? -999
                                          newVisitObject["weather_wind_deg"] = oldObject["weather_wind_deg"] as? Double ?? -999
                                          
                                      }
                                      
                                      else {
                                          
                                          let newLocationObject = migration.create("LocationObject")
                                          
                                          newLocationObject["identifier"] = oldObject["identifier"] as? String ?? UUID().uuidString
                                          
                                          newLocationObject["geo_latitude"] = oldObject["geo_latitude"] as? Double ?? 0
                                          newLocationObject["geo_longitude"] = oldObject["geo_longitude"] as? Double ?? 0
                                          newLocationObject["geo_accuracy"] = oldObject["geo_accuracy"] as? Double ?? 0
                                          
                                          newLocationObject["ts_timestamp"] = oldObject["ts_arrival"] as? Double ?? 0
                                          
                                          newLocationObject["isHidden"] = oldObject["isHidden"] as? Bool ?? false
                                          
                                          newLocationObject["workoutUUID"] = oldObject["info_workout"] as? String ?? ""
                                          
                                      }
                                      
                                      if let newObject = newObject {
                                          
                                          migration.delete(newObject)
                                          
                                      }
                                      
                                  }
                                  
                              }
                              
                              if oldSchemaVersion < 4005 && oldSchemaVersion > 4000 {
                                  
                                  migration.enumerateObjects(ofType: "LocationObject") { oldObject, newObject in
                                      
                                      guard let oldObject = oldObject else { return }
                                      
                                      if oldObject["ts_arrival"] as? Double ?? 0 != oldObject["ts_departure"] as? Double ?? 0 {
                                          
                                          let newVisitObject = migration.create("VisitObject")
                                          
                                          newVisitObject["identifier"] = oldObject["identifier"] as? String ?? UUID().uuidString
                                          
                                          newVisitObject["geo_latitude"] = oldObject["geo_latitude"] as? Double ?? 0
                                          newVisitObject["geo_longitude"] = oldObject["geo_longitude"] as? Double ?? 0
                                          newVisitObject["geo_accuracy"] = oldObject["geo_accuracy"] as? Double ?? 0
                                          
                                          newVisitObject["ts_arrival"] = oldObject["ts_arrival"] as? Double ?? 0
                                          newVisitObject["ts_departure"] = oldObject["ts_departure"] as? Double ?? 0
                                          newVisitObject["ts_timezone"] = oldObject["ts_timezone"] as? String ?? TimeZone.autoupdatingCurrent.identifier
                                          
                                          newVisitObject["isHidden"] = oldObject["isHidden"] as? Bool ?? false
                                          newVisitObject["isFixed"] = oldObject["isFixed"] as? Bool ?? false
                                          newVisitObject["isEdited"] = oldObject["isEdited"] as? Bool ?? false
                                          newVisitObject["isHighlight"] = false
                                          
                                          newVisitObject["info_rating"] = oldObject["info_rating"] as? Double ?? 0
                                          newVisitObject["info_notes"] = oldObject["info_notes"] as? String ?? ""
                                          newVisitObject["info_placemark"] = oldObject["info_placemark"] as? String ?? ""
                                          newVisitObject["info_transport"] = 0
                                          
                                          newVisitObject["weather_condition"] = oldObject["weather_condition"] as? Double ?? -999
                                          newVisitObject["weather_temperature"] = oldObject["weather_temperature"] as? Double ?? -999
                                          newVisitObject["weather_feels"] = oldObject["weather_feels"] as? Double ?? -999
                                          newVisitObject["weather_humidity"] = oldObject["weather_humidity"] as? Double ?? -999
                                          newVisitObject["weather_wind_speed"] = oldObject["weather_wind_speed"] as? Double ?? -999
                                          newVisitObject["weather_wind_deg"] = oldObject["weather_wind_deg"] as? Double ?? -999
                                          
                                      }
                                      
                                      else {
                                          
                                          let newLocationObject = migration.create("LocationObject")
                                          
                                          newLocationObject["identifier"] = oldObject["identifier"] as? String ?? UUID().uuidString
                                          
                                          newLocationObject["geo_latitude"] = oldObject["geo_latitude"] as? Double ?? 0
                                          newLocationObject["geo_longitude"] = oldObject["geo_longitude"] as? Double ?? 0
                                          newLocationObject["geo_accuracy"] = oldObject["geo_accuracy"] as? Double ?? 0
                                          
                                          newLocationObject["ts_timestamp"] = oldObject["ts_arrival"] as? Double ?? 0
                                          
                                          newLocationObject["isHidden"] = oldObject["isHidden"] as? Bool ?? false
                                          
                                          newLocationObject["workoutUUID"] = oldObject["healthkit_workout_identifier"] as? String ?? ""
                                          
                                      }
                                      
                                      if let newObject = newObject {
                                          
                                          migration.delete(newObject)
                                          
                                      }
                                      
                                  }
                                  
                              }
                              
                          }
                          
                      }
                      
                      
                      let realm = try Realm(configuration: realmConfiguration)
                      
                      
                      localDatabase.visits.removeAll()
                      localDatabase.isInitialized = false
                      localDatabase.labels.removeAll()
                      localDatabase.firstLocation = nil
                      localDatabase.firstVisit = nil
                      localDatabase.lastVisit = nil
                      localDatabase.lastLocation = nil
                      
                      
                      if let lastLocation = realm.objects(LocationObject.self).sorted(byKeyPath: "ts_timestamp", ascending: true).last {
                          
                          localDatabase.lastLocation = LocationObject(value: lastLocation)
                          
                      }
                      
                      if let firstLocation = realm.objects(LocationObject.self).sorted(byKeyPath: "ts_timestamp", ascending: true).first {
                          
                          localDatabase.firstLocation = LocationObject(value: firstLocation)
                          
                      }
                      
                      localDatabase.visits = Array(realm.objects(VisitObject.self).sorted(byKeyPath: "ts_arrival", ascending: false).freeze())
                      
                      localDatabase.labels = Array(realm.objects(LabelObject.self).sorted(byKeyPath: "info_text", ascending: true).freeze())
                      
                      localDatabase.isInitialized = true
                      
                      logEvent(function: "\(#function)", event: "Database has been initialized, \(compactStatus)")
                      
                      completion()
                      
                  }
                  
                  catch {
                      
                      logEvent(function: "\(#function)", event: "Database operation has failed with error \(error.localizedDescription)")
                      
                      print("FAILURE \(error.localizedDescription)")
                      
                      completion()
                      
                  }
                  
              }
              
          }
          
      }
      

      I'd be thankful if you could look into this issue.

      Thanks

      /Felix

            Assignee:
            jorgen.edelbo@mongodb.com Jørgen Edelbo
            Reporter:
            unitosyncbot Unito Sync Bot
            Votes:
            0 Vote for this issue
            Watchers:
            1 Start watching this issue

              Created:
              Updated:
              Resolved: