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)

Most upvoted comments

@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.isProtectedDataAvailable before deciding whether to use the database or not.