realm-swift
realm-swift copied to clipboard
EXC_BAD_ACCESS in get_number_of_versions()
How frequently does the bug occur?
Sometimes
Description
The App faces a EXC_BAD_ACCESS when it try to write an object.
Stacktrace & log output
0 Realm 0x197158 realm::DB::get_number_of_versions() + 24
1 Realm 0x450f18 check_can_create_write_transaction(realm::Realm const*) + 92
2 Realm 0x451d60 realm::Realm::begin_transaction() + 56
3 Realm 0x12bb24 -[RLMRealm beginWriteTransactionWithError:] + 24
4 RealmSwift 0x6d524 $s10RealmSwift0A0V5write16withoutNotifying_xSaySo20RLMNotificationTokenCG_xyKXEtKlF + 140
Can you reproduce the bug?
Not yet
Reproduction Steps
No response
Version
10.28.0
What SDK flavour are you using?
Local Database only
Are you using encryption?
Yes
Platform OS and version(s)
iOS 15.4.1 ~ 15.6.1 - multiple iPhone
Build environment
Xcode version: Xcode 13.3
Hi @mmar001 can you give us more context on how you are using Realm? (code samples, if threading is used, if encryption is used etc.)
saveOrUpdateToDb is the function that use db.write
that cause the crash.
func updateToDb<T: Object>(_ object: T) {
autoreleasepool {
guard let db = getDatabase() else { return }
do {
try db.write {
db.create(T.self, value: object, update: .all)
}
} catch let error as NSError {
logError(err: error)
}
}
}
private func getDatabase() -> Realm? {
return queue.sync {
do {
let db = try Realm(configuration: appConf)
fixRealmBackgroundCrash(config: appConf)
return db
} catch {
logError(err: error)
let databaseConfiguration = Realm.Configuration(
schemaVersion: DatabaseManager.currentSchemaVersion,
migrationBlock: DatabaseManager.migrationBlock
)
let db = try? Realm(configuration: databaseConfiguration)
fixRealmBackgroundCrash(config: databaseConfiguration)
return db
}
}
}
func fixRealmBackgroundCrash(config: Realm.Configuration) {
// Source: https://github.com/realm/realm-cocoa/issues/7112#issuecomment-778218878
let folderPath = config.fileURL!.deletingLastPathComponent().path
do {
let attributes = try FileManager.default.attributesOfItem(atPath: folderPath)
let protectionType = attributes[.protectionKey] as? FileProtectionType
if protectionType != .some(FileProtectionType.none) {
try FileManager.default.setAttributes([.protectionKey: FileProtectionType.none], ofItemAtPath: folderPath)
}
} catch {
log("Unable to set protection attributes for realm folder: \(error)")
}
}
We use encryption and below is how we gat/create the db:
private var appConfiguration: Realm.Configuration
private init() {
appConfiguration = getDatabaseConfiguration()
}
func getDatabaseConfiguration() -> Realm.Configuration{
var databaseConfiguration = Realm.Configuration(
schemaVersion: currentSchemaVersion,
migrationBlock: DatabaseManager.migrationBlock,
deleteRealmIfMigrationNeeded: false
)
databaseConfiguration.fileURL = getPath()
let passphrase = getPassphrase()
if let data = Data(base64Encoded: passphrase, options: NSData.Base64DecodingOptions()), data.count == 64 {
databaseConfiguration.encryptionKey = data
} else if let data = passphrase.data(using: .utf8), data.count == 64 {
databaseConfiguration.encryptionKey = data
} else {
databaseConfiguration.encryptionKey = nil
}
return databaseConfiguration
}
@mmar001 are you able to send us a sample app that can reproduce this issue?
I cannot reproduce the issue. It is reported in Crashlytics and happens only to live user, not in debug . I see that in v10.28.5 there is a fix regarding the versioning, this could be related?
That fix is not related. We will require more full stacktraces to better understand what could be happening.
Below the full stacktrace. Realm runs in multiple thread in the app.
0 Realm 0x197158 realm::DB::get_number_of_versions() + 24
1 Realm 0x450f18 check_can_create_write_transaction(realm::Realm const*) + 92
2 Realm 0x451d60 realm::Realm::begin_transaction() + 56
3 Realm 0x12bb24 -[RLMRealm beginWriteTransactionWithError:] + 24
4 RealmSwift 0x6d524 $s10RealmSwift0A0V5write16withoutNotifying_xSaySo20RLMNotificationTokenCG_xyKXEtKlF + 140
…
8 libswiftObjectiveC.dylib 0x1a10 autoreleasepool<A>(invoking:) + 64
…
15 libdispatch.dylib 0x1e6c _dispatch_call_block_and_release + 32
16 libdispatch.dylib 0x3a30 _dispatch_client_callout + 20
17 libdispatch.dylib 0xb124 _dispatch_lane_serial_drain + 668
18 libdispatch.dylib 0xbc80 _dispatch_lane_invoke + 392
19 libdispatch.dylib 0x16500 _dispatch_workloop_worker_thread + 648
20 libsystem_pthread.dylib 0x10bc _pthread_wqthread + 288
21 libsystem_pthread.dylib 0xe5c start_wqthread + 8
com.apple.main-thread
0 libsystem_kernel.dylib 0x14a0 mach_msg_trap + 8
1 libsystem_kernel.dylib 0x1ae4 mach_msg + 76
2 CoreFoundation 0x6d30 __CFRunLoopServiceMachPort + 372
3 CoreFoundation 0xb1bc __CFRunLoopRun + 1180
4 CoreFoundation 0x1ebc8 CFRunLoopRunSpecific + 600
5 GraphicsServices 0x1374 GSEventRunModal + 164
6 UIKitCore 0x514b58 -[UIApplication _run] + 1100
7 UIKitCore 0x296090 UIApplicationMain + 364
8 DE 0x579148 main + 18 (AppDelegate.swift:18)
9 ??? 0x1054adda4 (Missing)
com.apple.uikit.eventfetch-thread
0 libsystem_kernel.dylib 0x14a0 mach_msg_trap + 8
1 libsystem_kernel.dylib 0x1ae4 mach_msg + 76
2 CoreFoundation 0x6d30 __CFRunLoopServiceMachPort + 372
3 CoreFoundation 0xb1bc __CFRunLoopRun + 1180
4 CoreFoundation 0x1ebc8 CFRunLoopRunSpecific + 600
5 Foundation 0x19444 -[NSRunLoop(NSRunLoop) runMode:beforeDate:] + 236
6 Foundation 0x5ae0c -[NSRunLoop(NSRunLoop) runUntilDate:] + 92
7 UIKitCore 0x48ecc4 -[UIEventFetcher threadMain] + 524
8 Foundation 0x6941c __NSThread__start__ + 808
9 libsystem_pthread.dylib 0x19ac _pthread_start + 148
10 libsystem_pthread.dylib 0xe68 thread_start + 8
queue.wifiDet
0 libsystem_kernel.dylib 0x4ba4 poll + 8
…
16 libdispatch.dylib 0x1e6c _dispatch_call_block_and_release + 32
17 libdispatch.dylib 0x3a30 _dispatch_client_callout + 20
18 libdispatch.dylib 0xb124 _dispatch_lane_serial_drain + 668
19 libdispatch.dylib 0xbc80 _dispatch_lane_invoke + 392
20 libdispatch.dylib 0x16500 _dispatch_workloop_worker_thread + 648
21 libsystem_pthread.dylib 0x10bc _pthread_wqthread + 288
22 libsystem_pthread.dylib 0xe5c start_wqthread + 8
queue.Network
0 libsystem_kernel.dylib 0x242c read + 8
…
27 libdispatch.dylib 0x1e6c _dispatch_call_block_and_release + 32
28 libdispatch.dylib 0x3a30 _dispatch_client_callout + 20
29 libdispatch.dylib 0xb124 _dispatch_lane_serial_drain + 668
30 libdispatch.dylib 0xbc80 _dispatch_lane_invoke + 392
31 libdispatch.dylib 0x16500 _dispatch_workloop_worker_thread + 648
32 libsystem_pthread.dylib 0x10bc _pthread_wqthread + 288
33 libsystem_pthread.dylib 0xe5c start_wqthread + 8
com.google.firebase.crashlytics.MachExceptionServer
0 FirebaseCrashlytics 0x1cf2c FIRCLSProcessRecordAllThreads + 184
1 FirebaseCrashlytics 0x1d30c FIRCLSProcessRecordAllThreads + 1176
2 FirebaseCrashlytics 0x1617c FIRCLSHandler + 48
3 FirebaseCrashlytics 0x18f44 FIRCLSMachExceptionServer + 1236
4 libsystem_pthread.dylib 0x19ac _pthread_start + 148
5 libsystem_pthread.dylib 0xe68 thread_start + 8
queue.devices
0 libsystem_kernel.dylib 0x4ba4 poll + 8
…
16 libdispatch.dylib 0x1e6c _dispatch_call_block_and_release + 32
17 libdispatch.dylib 0x3a30 _dispatch_client_callout + 20
18 libdispatch.dylib 0xb124 _dispatch_lane_serial_drain + 668
19 libdispatch.dylib 0xbc80 _dispatch_lane_invoke + 392
20 libdispatch.dylib 0x16500 _dispatch_workloop_worker_thread + 648
21 libsystem_pthread.dylib 0x10bc _pthread_wqthread + 288
22 libsystem_pthread.dylib 0xe5c start_wqthread + 8
com.apple.NSURLConnectionLoader
0 libsystem_kernel.dylib 0x14a0 mach_msg_trap + 8
1 libsystem_kernel.dylib 0x1ae4 mach_msg + 76
2 CoreFoundation 0x6d30 __CFRunLoopServiceMachPort + 372
3 CoreFoundation 0xb1bc __CFRunLoopRun + 1180
4 CoreFoundation 0x1ebc8 CFRunLoopRunSpecific + 600
5 CFNetwork 0x2781dc _CFURLStorageSessionDisableCache + 60032
6 Foundation 0x6941c __NSThread__start__ + 808
7 libsystem_pthread.dylib 0x19ac _pthread_start + 148
8 libsystem_pthread.dylib 0xe68 thread_start + 8
Realm notification listener
0 libsystem_kernel.dylib 0x2e18 kevent + 8
1 Realm 0x3aaf04 realm::_impl::ExternalCommitHelper::listen() + 156
2 Realm 0x3ab054 void* std::__1::__thread_proxy<std::__1::tuple<std::__1::unique_ptr<std::__1::__thread_struct, std::__1::default_delete<std::__1::__thread_struct> >, realm::_impl::ExternalCommitHelper::ExternalCommitHelper(realm::_impl::RealmCoordinator&)::$_0> >(void*) + 52
3 libsystem_pthread.dylib 0x19ac _pthread_start + 148
4 libsystem_pthread.dylib 0xe68 thread_start + 8
queue.provider
0 libsystem_kernel.dylib 0x242c read + 8
…
27 libdispatch.dylib 0x1e6c _dispatch_call_block_and_release + 32
28 libdispatch.dylib 0x3a30 _dispatch_client_callout + 20
29 libdispatch.dylib 0xb124 _dispatch_lane_serial_drain + 668
30 libdispatch.dylib 0xbc80 _dispatch_lane_invoke + 392
31 libdispatch.dylib 0x16500 _dispatch_workloop_worker_thread + 648
32 libsystem_pthread.dylib 0x10bc _pthread_wqthread + 288
33 libsystem_pthread.dylib 0xe5c start_wqthread + 8
Thread
0 libsystem_kernel.dylib 0x1a74 __workq_kernreturn + 8
1 libsystem_pthread.dylib 0x1108 _pthread_wqthread + 364
2 libsystem_pthread.dylib 0xe5c start_wqthread + 8
Thread
0 libsystem_kernel.dylib 0x1a74 __workq_kernreturn + 8
1 libsystem_pthread.dylib 0x1108 _pthread_wqthread + 364
2 libsystem_pthread.dylib 0xe5c start_wqthread + 8
Thread
0 libsystem_kernel.dylib 0x1a74 __workq_kernreturn + 8
1 libsystem_pthread.dylib 0x1108 _pthread_wqthread + 364
2 libsystem_pthread.dylib 0xe5c start_wqthread + 8```
For running Realm on different threads, you need to confine the Realm to a queue. Can you try something along the lines of:
func updateToDb<T: Object>(_ object: T, on queue: DispatchQueue) {
queue.async {
autoreleasepool {
guard let db = getDatabase(on: queue) else { return }
do {
try db.write {
db.create(T.self, value: object, update: .all)
}
} catch let error as NSError {
logError(err: error)
}
}
}
}
private func getDatabase(on queue: DispatchQueue) -> Realm? {
do {
let db = try Realm(configuration: appConf, queue: queue)
fixRealmBackgroundCrash(config: appConf) // This should only ever run once, I recommend moving it else where.
return db
} catch {
logError(err: error)
let databaseConfiguration = Realm.Configuration(
schemaVersion: DatabaseManager.currentSchemaVersion,
migrationBlock: DatabaseManager.migrationBlock
)
let db = try? Realm(configuration: databaseConfiguration, queue: queue)
fixRealmBackgroundCrash(config: databaseConfiguration)
return db
}
}
@mmar001 did you take a look to the above comment?, I know there is no way to know this is fixed until you release a new version and you don't see the mentioned crash in your Crashlytics dashboard but it is really helpful to know if the issue continues or not.
Hello, yes we apply it but the crash is not fixed yet