realm / realm-swift

Realm is a mobile database: a replacement for Core Data & SQLite
https://realm.io
Apache License 2.0
16.31k stars 2.14k forks source link

mmap() failed: Cannot allocate memory size: 1048576 #6063

Closed dsanghan closed 5 years ago

dsanghan commented 5 years ago

Goals

Realm works without crashing in all scenarios

Expected Results

Realm works without crashing

Actual Results

Realm crashes when transactions are committed in the background or when coming out of background.

Info

I've read the other stackoverflow posts as well as the realm issues that suggest using shouldCompactOnLaunch. I've implemented it in our latest release, but still see this crash.

I've verified that the database is ~ 5MB in size.

This crash only happens when the app is either in background or coming out of background.

In every crash log, the allocation failure is for the same size (1048576). I've confirmed the DB is not growing arbitrarily large.

Fatal Exception: RLMException
mmap() failed: Cannot allocate memory size: 1048576

0  CoreFoundation                 0x1e82a8ec4 __exceptionPreprocess
1  libobjc.A.dylib                0x1e7479a40 objc_exception_throw
2  Canary-iOS                     0x102b91e90 RLMSetErrorOrThrow(NSError*, NSError* __autoreleasing*) (RLMUtil.mm:336)
3  Canary-iOS                     0x102b64450 RLMRealmTranslateException(NSError* __autoreleasing*) (RLMRealm.mm:316)
4  Canary-iOS                     0x102b662bc -[RLMRealm commitWriteTransaction:] (RLMRealm.mm:591)
5  Canary-iOS                     0x10278c70c -[CanaryCoreRealmManager synchronizeLogsChangesSync] (CanaryCoreRealmManager.m:943)
6  libdispatch.dylib              0x1e7ce16c8 _dispatch_call_block_and_release
7  libdispatch.dylib              0x1e7ce2484 _dispatch_client_callout
8  libdispatch.dylib              0x1e7c89bd0 _dispatch_lane_serial_drain$VARIANT$mp
9  libdispatch.dylib              0x1e7c8a718 _dispatch_lane_invoke$VARIANT$mp
10 libdispatch.dylib              0x1e7c92eb8 _dispatch_workloop_worker_thread
11 libsystem_pthread.dylib        0x1e7ec50dc _pthread_wqthread
12 libsystem_pthread.dylib        0x1e7ec7cec start_wqthread

Code Sample

- (void)synchronizeLogsChangesSync {
    @autoreleasepool {
        NSArray *updates = self.logsUpdateQueue.popAllObjects;
        if (updates.count > 0) {
            RLMRealm *realm = [self realmForCurrentThread];
            [realm beginWriteTransaction];
            [realm addObjects:updates];
            [realm commitWriteTransaction];
        }
    }
}

Version of Realm and Tooling

ProductName:    Mac OS X
ProductVersion: 10.14.1
BuildVersion:   18B75

/Applications/Xcode.app/Contents/Developer
Xcode 10.1
Build version 10B61

/Users/dev/.rvm/rubies/ruby-2.4.2/bin/pod
1.5.3
Realm (3.13.0)
tgoyne commented 5 years ago

If it only happens while the app is in the background it's probably related to NSFileProtection, although I've never heard of file protection causing problems in this specific way. If you can reproduce the problem yourself, you could try disabling file protection just to see if it is related.

The actual error that's happening here is that once we're at the writing to the file step of committing a write transaction, we map 1 MB writeable windows for each of the parts of the file that we need to write to (normally the Realm is mapped as read-only). This normally can only fail if the process is out of address space (almost certainly not the problem here) or if we don't have permission to write to the file. If you use commitWriteTransactionWithError: to get an NSError object when the write fails it should have the original error code that says why exactly mmap() failed.

caravaneer404 commented 5 years ago

Hi! 5% of users have same problems. We using RealmSwift and have tried to disable encryption and/or shouldCompactOnLaunch as we saw it in others issues, but it does not work. I guess this bug reproduced only in release configuration, because I've never seen it during development.

My config code:

        var config = Realm.Configuration()
        config.schemaVersion = 40
        config.shouldCompactOnLaunch = { totalBytes, usedBytes in
            let oneHundredMB = 100 * 1_024 * 1_024
            return (totalBytes > oneHundredMB) && (Double(usedBytes) / Double(totalBytes)) < 0.5
        }

        config.migrationBlock = { migration, oldSchemaVersion in
            if oldSchemaVersion < 34 {
                self.foo(migration: migration)
            }
        }

        Realm.Configuration.defaultConfiguration = config

One of my crashlogs:

Fatal error: 'try!' expression unexpectedly raised an error: Error Domain=io.realm Code=9 "mmap() failed: Cannot allocate memory size: 2415919104 offset: 0" UserInfo={NSLocalizedDescription=mmap() failed: Cannot allocate memory size: 2415919104 offset: 0, Error Code=9}: file /BuildRoot/Library/Caches/com.apple.xbs/Sources/swiftlang_Fall2018/swiftlang_Fall2018-1000.11.42/src/swift/stdlib/public/core/ErrorType.swift, line 184 2019-01-17 17:12:47.831878+0300 Express[44069:14842020] Fatal error: 'try!' expression unexpectedly raised an error: Error Domain=io.realm Code=9 "mmap() failed: Cannot allocate memory size: 2415919104 offset: 0" UserInfo={NSLocalizedDescription=mmap() failed: Cannot allocate memory size: 2415919104 offset: 0, Error Code=9}: file /BuildRoot/Library/Caches/com.apple.xbs/Sources/swiftlang_Fall2018/swiftlang_Fall2018-1000.11.42/src/swift/stdlib/public/core/ErrorType.swift, line 184

This is fresh install, realm file should not be this size, 10mb max.

dsanghan commented 5 years ago

@tgoyne You were right, the address space was being consumed by another library in specific cases when the iOS app was fetching in the background. I've opened an issue in that library. Thanks!

realm-probot[bot] commented 5 years ago

Hey - looks like you forgot to add a T:* label - could you please add one?

vtkumaresan commented 5 years ago

hi guys, issue still exist but ticket was closed. Tested in latest version of realmswift,

Version updated, Installing RealmSwift 3.17.0 (was 3.16.2)

Tested device: iPhone 6s

Available free storage, 40GB

Error, mmap() failed: Cannot allocate memory size: 2415919104 offset: 0

kevinduellman commented 4 years ago

@dsanghan Could you post the library you saw this issue in?

samgold89 commented 4 years ago

I'm seeing the same crash. A lot. Any updates here?

dsanghan commented 4 years ago

@kduellman I was seeing because of https://github.com/MailCore/mailcore2 - the threads being created for IDLE connections were leaking in the background, making the app run out of address space. Once that was resolved, we stopped seeing this realm crash completely.

samgold89 commented 4 years ago

I'm seeing this same crash consistently when leaving the app running for more than ~5 minutes. @dsanghan - how were you able to diagnose that third-party leak?