realm-swift: iOS crash due to default.realm.lock': open() failed: Operation not permitted Path
How frequently does the bug occur?
Sometimes
Description
Expected The crash shouldn’t happen.
Actual result
The crash happens during app startup process. We did a database migration in function application:didFinishLaunchingWithOptions in AppDelegate.m
Stacktrace & log output
Fatal Exception: RLMException
/var/mobile/Containers/Data/Application/8025F2F4-E299-4025-AE69-A441B9D27B48/Documents/RealmDB/default.realm.lock: Unable to open a realm at path '/var/mobile/Containers/Data/Application/8025F2F4-E299-4025-AE69-A441B9D27B48/Documents/RealmDB/default.realm.lock': open() failed: Operation not permitted Path: /var/mobile/Containers/Data/Application/8025F2F4-E299-4025-AE69-A441B9D27B48/Documents/RealmDB/default.realm.lock Exception backtrace: 0 MyAppName 0x0000000104ad8734 _ZNK5realm5Table10find_firstINS_4util8OptionalINS_8ObjectIdEEEEENS_6ObjKeyENS_6ColKeyET_ + 106252 1 MyAppName 0x00000001049b55b0 _ZNK5realm19ArrayFixedBytesNullINS_4UUIDELi16EE15find_first_nullEmm + 124732 2 MyAppName 0x00000001049b864c _ZNK5realm19ArrayFixedBytesNullINS_4UUIDELi16EE15find_first_nullEmm + 137176 3 MyAppName 0x00000001049bc8e4 _ZNK5realm19ArrayFixedBytesNullINS_4UUIDELi16EE15find_first_nullEmm + 154224 4 MyAppName 0x0000000104b9d41c _ZNK5realm5Table10find_firstINS_4util8OptionalINS_8ObjectIdEEEEENS_6ObjKeyENS_6ColKeyET_ + 912372 5 MyAppName 0x0000000104b9c548 _ZNK5realm5Table10find_firstINS_4util8OptionalINS_8ObjectIdEEEEENS_6ObjKeyENS_6ColKeyET_ + 908576 6 MyAppName 0x0000000104b9c3a0 _ZNK5realm5Table10find_firstINS_4util8OptionalINS_8ObjectIdEEEEENS_6ObjKeyENS_6ColKeyET_ + 908152 7 MyAppName 0x0000000104beaf40 _ZN5realm7Results8index_ofINS_4util8OptionalINS_4UUIDEEEEEmRKT_ + 73892 8 MyAppName 0x00000001048aadf4 _Z23RLMAddNotificationBlockI10RLMResultsEP20RLMNotificationTokenPT_U13block_pointerFvP11objc_objectP19RLMCollectionChangeP7NSErrorEPU28objcproto17OS_dispatch_queue8NSObject + 665224 9 MyAppName 0x00000001048aaa2c _Z23RLMAddNotificationBlockI10RLMResultsEP20RLMNotificationTokenPT_U13block_pointerFvP11objc_objectP19RLMCollectionChangeP7NSErrorEPU28ob
Fatal Exception: RLMException
0 CoreFoundation 0x12586c __exceptionPreprocess
1 libobjc.A.dylib 0x6c50 objc_exception_throw
2 MyAppName 0x39f9f0 RLMSetErrorOrThrow(NSError*, NSError* __autoreleasing*) + 380 (RLMUtil.mm:380)
3 MyAppName 0x382404 RLMRealmTranslateException(NSError* __autoreleasing*) + 327 (RLMRealm.mm:327)
4 MyAppName 0x3838ec translateSharedGroupOpenException(NSError* __autoreleasing*) + 357 (RLMRealm.mm:357)
5 MyAppName 0x383830 +[RLMRealm realmWithConfiguration:queue:error:] + 445 (RLMRealm.mm:445)
6 MyAppName 0x382a2c +[RLMRealm realmWithConfiguration:error:] + 362 (RLMRealm.mm:362)
7 MyAppName 0x381974 +[RLMRealm defaultRealm] + 197 (RLMRealm.mm:197)
8 MyAppName 0x843c -[AppDelegate migrateRealmDB] + 151 (AppDelegate.m:151)
9 MyAppName 0x7d54 -[AppDelegate application:didFinishLaunchingWithOptions:] + 28 (AppDelegate.m:28)
10 UIKitCore 0xbc5228 -[UIApplication _handleDelegateCallbacksWithOptions:isSuspended:restoreState:]
11 UIKitCore 0xbc7290 -[UIApplication _callInitializationDelegatesWithActions:forCanvas:payload:fromOriginatingProcess:]
12 UIKitCore 0xbcccec -[UIApplication _runWithMainScene:transitionContext:completion:]
13 UIKitCore 0x222c74 -[_UISceneLifecycleMultiplexer completeApplicationLaunchWithFBSScene:transitionContext:]
14 UIKitCore 0x790f9c _UIScenePerformActionsWithLifecycleActionMask
15 UIKitCore 0x22380c __101-[_UISceneLifecycleMultiplexer _evalTransitionToSettings:fromSettings:forceExit:withTransitionStore:]_block_invoke
16 UIKitCore 0x2232cc -[_UISceneLifecycleMultiplexer _performBlock:withApplicationOfDeactivationReasons:fromReasons:]
17 UIKitCore 0x22361c -[_UISceneLifecycleMultiplexer _evalTransitionToSettings:fromSettings:forceExit:withTransitionStore:]
18 UIKitCore 0x222e58 -[_UISceneLifecycleMultiplexer uiScene:transitionedFromState:withTransitionContext:]
19 UIKitCore 0x22b3a4 __186-[_UIWindowSceneFBSSceneTransitionContextDrivenLifecycleSettingsDiffAction _performActionsForUIScene:withUpdatedFBSScene:settingsDiff:fromSettings:transitionContext:lifecycleActionType:]_block_invoke
20 UIKitCore 0x69d60c +[BSAnimationSettings(UIKit) tryAnimatingWithSettings:actions:completion:]
21 UIKitCore 0x7a96c4 _UISceneSettingsDiffActionPerformChangesWithTransitionContext
22 UIKitCore 0x22b09c -[_UIWindowSceneFBSSceneTransitionContextDrivenLifecycleSettingsDiffAction _performActionsForUIScene:withUpdatedFBSScene:settingsDiff:fromSettings:transitionContext:lifecycleActionType:]
23 UIKitCore 0x525a0 __64-[UIScene scene:didUpdateWithDiff:transitionContext:completion:]_block_invoke
24 UIKitCore 0x50f14 -[UIScene _emitSceneSettingsUpdateResponseForCompletion:afterSceneUpdateWork:]
25 UIKitCore 0x521c8 -[UIScene scene:didUpdateWithDiff:transitionContext:completion:]
26 UIKitCore 0xbcae8c -[UIApplication workspace:didCreateScene:withTransitionContext:completion:]
27 UIKitCore 0x6c6e38 -[UIApplicationSceneClientAgent scene:didInitializeWithEvent:completion:]
28 FrontBoardServices 0xa3bc -[FBSScene _callOutQueue_agent_didCreateWithTransitionContext:completion:]
29 FrontBoardServices 0x35d04 __94-[FBSWorkspaceScenesClient createWithSceneID:groupID:parameters:transitionContext:completion:]_block_invoke.200
30 FrontBoardServices 0x194a0 -[FBSWorkspace _calloutQueue_executeCalloutFromSource:withBlock:]
31 FrontBoardServices 0x359c8 __94-[FBSWorkspaceScenesClient createWithSceneID:groupID:parameters:transitionContext:completion:]_block_invoke
32 libdispatch.dylib 0x3db0 _dispatch_client_callout
33 libdispatch.dylib 0x7738 _dispatch_block_invoke_direct
34 FrontBoardServices 0x5e250 __FBSSERIALQUEUE_IS_CALLING_OUT_TO_A_BLOCK__
35 FrontBoardServices 0x5dee0 -[FBSSerialQueue _targetQueue_performNextIfPossible]
36 FrontBoardServices 0x5e434 -[FBSSerialQueue _performNextFromRunLoopSource]
37 CoreFoundation 0xa176c __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__
38 CoreFoundation 0xa1668 __CFRunLoopDoSource0
39 CoreFoundation 0xa0960 __CFRunLoopDoSources0
40 CoreFoundation 0x9aa8c __CFRunLoopRun
41 CoreFoundation 0x9a21c CFRunLoopRunSpecific
42 GraphicsServices 0x3784 GSEventRunModal
43 UIKitCore 0xbc8ee8 -[UIApplication _run]
44 UIKitCore 0xbce75c UIApplicationMain
45 MyAppName 0x8c24 main + 14 (main.m:14)
46 libdyld.dylib 0x16b0 start
Can you reproduce the bug?
Not yet
Reproduction Steps
This crash is found on the Firebase console, I can’t reproduce it. According to the Firebase, it happens more than 600 times and affects more than 300 users. I tried solutions in other issues below:
https://github.com/realm/realm-swift/issues/3308#issuecomment-195621569 https://github.com/realm/realm-swift/issues/5938#issuecomment-439522830 https://github.com/realm/realm-swift/issues/1260#issuecomment-223842622 https://github.com/realm/realm-swift/issues/1874#issuecomment-101057887 https://github.com/realm/realm-swift/issues/1571#issuecomment-77901737
And I even looked up the docs https://docs.mongodb.com/realm-legacy/docs/swift/latest/index.html#using-realm-with-background-app-refresh, but after updating my code I still see this crash happens on the production environment.
Here are my code about migration
- (void)migrateRealmDB {
NSString *kRealmFileName = @"default.realm";
NSString *kRealmLockFileName = @"default.realm.lock";
NSString *kRealmManagementFolder = @"default.realm.management";
NSString *documentFolder = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) firstObject];
NSString *dbfolder = [documentFolder stringByAppendingPathComponent:@"RealmDB"];
NSString *newRealmPath = [dbfolder stringByAppendingPathComponent:kRealmFileName];
BOOL isDirectory = YES;
BOOL folderExists = [[NSFileManager defaultManager] fileExistsAtPath:dbfolder isDirectory:&isDirectory];
if (!folderExists) {
BOOL res = [[NSFileManager defaultManager] createDirectoryAtPath:dbfolder
withIntermediateDirectories:YES
attributes:@{ NSFileProtectionKey: NSFileProtectionNone }
error:nil];
if (res) {
// create folder successfully
folderExists = YES;
NSString *defaultRealmPath = [documentFolder stringByAppendingPathComponent:kRealmFileName];
BOOL realmExists = [[NSFileManager defaultManager] fileExistsAtPath:defaultRealmPath];
if (realmExists) {
// need to move realm to RealmDB folder
NSString *defaultRealmLock = [documentFolder stringByAppendingPathComponent:kRealmLockFileName];
NSString *defaultRealmFolder = [documentFolder stringByAppendingPathComponent:kRealmManagementFolder];
NSString *newRealmLock = [dbfolder stringByAppendingPathComponent:kRealmLockFileName];
NSString *newRealmFolder = [dbfolder stringByAppendingPathComponent:kRealmManagementFolder];
[[NSFileManager defaultManager] moveItemAtPath:defaultRealmPath toPath:newRealmPath error:nil];
[[NSFileManager defaultManager] moveItemAtPath:defaultRealmFolder toPath:newRealmFolder error:nil];
[[NSFileManager defaultManager] moveItemAtPath:defaultRealmLock toPath:newRealmLock error:nil];
}
}
}
// migrate database
RLMRealmConfiguration *config = [RLMRealmConfiguration defaultConfiguration];
// Set the new schema version. This must be greater than the previously used
// version (if you've never set a schema version before, the version is 0).
config.schemaVersion = 1;
if (folderExists) {
config.fileURL = [NSURL URLWithString:newRealmPath];
}
// Set the block which will be called automatically when opening a Realm with a
// schema version lower than the one set above
config.migrationBlock = ^(RLMMigration *migration, uint64_t oldSchemaVersion) {
// We haven’t migrated anything yet, so oldSchemaVersion == 0
if (oldSchemaVersion < 1) {
// Nothing to do!
// Realm will automatically detect new properties and removed properties
// And will update the schema on disk automatically
}
};
// Tell Realm to use this new configuration object for the default Realm
[RLMRealmConfiguration setDefaultConfiguration:config];
// Now that we've told Realm how to handle the schema change, opening the file
// will automatically perform the migration
[RLMRealm defaultRealm];
}
I created a sub directory in document folder, move the default.realm file and default.realm.lock file to this sub directory and set its attribution to NSFileProtectionNone, but still seeing this crash on the production environment.
Version
Realm 10.7.2
What SDK flavour are you using?
Local Database only
Are you using encryption?
No, not using encryption
Platform OS and version(s)
iOS 14
Build environment
Xcode version: 13.1 Dependency manager and version: CocoaPods 1.11.3
About this issue
- Original URL
- State: closed
- Created 2 years ago
- Comments: 17 (6 by maintainers)
@nalexn thanks for the details, I’ll bring this topic back up for discussion with the team to see if anything can be done.
Just in case it’s useful for anyone else with this issue, we tracked it down in our app to the MFi App Launch feature, where if the user powered on their iOS device but didn’t unlock it, when the MFi Bluetooth device was powered on and the app launched (underneath the locked screen) any access to files in the app’s documents folder would fail with the same error seen in this report. The Crashlytics issue in our case also showed the app as not being in the background, but this isn’t totally true - it’s underneath the lock screen, not in the background 😉
So this could occur if the app makes use of any feature that could launch the app before the user has ever unlocked the device (geofencing maybe?)
Our initial workaround is checking
UIApplication.shared.isProtectedDataAvailablebefore deciding whether to use the database or not.