Realm-cocoa: Crash: Cannot create asynchronous query while in a write transaction

Created on 18 Oct 2016  路  22Comments  路  Source: realm/realm-cocoa

Goals

Avoid crashes.

Expected Results

Crashes do not happen.
Also I want to know what kind of code can lead to this crash.

Actual Results

Possible related threads are below.

Fatal Exception: realm::InvalidTransactionException: Cannot create asynchronous query while in a write transaction



Crashed: com.twitter.crashlytics.ios.exception
0  ??????                         0xfefe19 CLSProcessRecordAllThreads + 17612313
1  ??????                         0xfefe19 CLSProcessRecordAllThreads + 17612313
2  ??????                         0xfefd11 CLSProcessRecordAllThreads + 17612049
3  ??????                         0xfe41ef CLSHandler + 17564143
4  ??????                         0xfee787 __CLSExceptionRecord_block_invoke + 17606535
5  libdispatch.dylib              0x3a3f47a7 _dispatch_client_callout + 22
6  libdispatch.dylib              0x3a3fbac9 _dispatch_barrier_sync_f_invoke + 48
7  ??????                         0xfee189 CLSExceptionRecord + 17605001
8  ??????                         0xfedba3 CLSTerminateHandler() + 17603491
9  libc++abi.dylib                0x397cdde3 std::__terminate(void (*)()) + 78
10 libc++abi.dylib                0x397cd8af __cxa_rethrow + 102
11 libobjc.A.dylib                0x39e94dd3 objc_exception_rethrow + 42
12 CoreFoundation                 0x2c5ec45d CFRunLoopRunSpecific + 632
13 CoreFoundation                 0x2c5ec1d3 CFRunLoopRunInMode + 106
14 GraphicsServices               0x339ea0a9 GSEventRunModal + 136
15 UIKit                          0x2fbfa7b1 UIApplicationMain + 1440
16 ??????                         0xefea7 main (main.m:14)
17 libdyld.dylib                  0x3a414aaf start + 2


RLMRealm notification listener
0  libsystem_kernel.dylib         0x3a4caa18 kevent + 24
1  Realm                          0x17aea25 realm::_impl::ExternalCommitHelper::listen() (external_commit_helper.cpp:200)
2  Realm                          0x17aed0b std::__1::__async_func<realm::_impl::ExternalCommitHelper::ExternalCommitHelper(realm::_impl::RealmCoordinator&)::$_0>::operator()() (external_commit_helper.cpp:159)
3  Realm                          0x17aec23 std::__1::__async_assoc_state<void, std::__1::__async_func<realm::_impl::ExternalCommitHelper::ExternalCommitHelper(realm::_impl::RealmCoordinator&)::$_0> >::__execute() (future:1026)
4  Realm                          0x17aeeaf std::__1::__thread_proxy<std::__1::tuple<void (std::__1::__async_assoc_state<void, std::__1::__async_func<realm::_impl::ExternalCommitHelper::ExternalCommitHelper(realm::_impl::RealmCoordinator&)::$_0> >::*)(), std::__1::__async_assoc_state<void, std::__1::__async_func<realm::_impl::ExternalCommitHelper::ExternalCommitHelper(realm::_impl::RealmCoordinator&)::$_0> >*> >(void*, void*) (__functional_base:383)
5  libsystem_pthread.dylib        0x3a557e93 _pthread_body + 138
6  libsystem_pthread.dylib        0x3a557e07 _pthread_start + 118
7  libsystem_pthread.dylib        0x3a555b90 thread_start + 8


com.?????.???.realm
0  libsystem_kernel.dylib         0x3a4ca354 flock + 8
1  Realm                          0x1880891 realm::util::File::lock(bool, bool) + 124
2  Realm                          0x1948f1f realm::SharedGroup::do_begin_write() + 118
3  Realm                          0x1877c61 auto realm::_impl::transaction::begin(realm::SharedGroup&, realm::BindingContext*, bool)::$_1::operator()<(anonymous namespace)::TransactLogValidator>((anonymous namespace)::TransactLogValidator&&) const (group_shared.hpp:965)
4  Realm                          0x1872805 realm::_impl::transaction::begin(realm::SharedGroup&, realm::BindingContext*, bool) (vector:449)
5  Realm                          0x18704ed realm::Realm::begin_transaction() (shared_realm.cpp:348)
6  Realm                          0x185d083 -[RLMRealm beginWriteTransaction] (RLMRealm.mm:475)
7  ??????                         0xab44b __54-[BKLResourceViewLogManager updateResourceLogSuccess:]_block_invoke (BKLResourceViewLogManager.m:149)
8  libdispatch.dylib              0x3a3f47bb _dispatch_call_block_and_release + 10
9  libdispatch.dylib              0x3a3fc5b1 _dispatch_queue_drain + 952
10 libdispatch.dylib              0x3a3f6f85 _dispatch_queue_invoke + 84
11 libdispatch.dylib              0x3a3fdb9b _dispatch_root_queue_drain + 338
12 libdispatch.dylib              0x3a3fecd7 _dispatch_worker_thread3 + 94
13 libsystem_pthread.dylib        0x3a555e31 _pthread_wqthread + 668
14 libsystem_pthread.dylib        0x3a555b84 start_wqthread + 8

Steps to Reproduce

I do not know how to reproduce it.

I haven't got anything helpful after searching all the issues and in stackoverflow.com. And I also searched the crash message Cannot create asynchronous query while in a write transaction in realm source code but found nothing. It's not a new issue and I first found this crash about one month ago.

Code Sample

I've read the doc and cannot find what's wrong with my code. I know how to avoid common problems like nested transactions. But this one is killing me.

Is it possible to trace backwards? I mean find out which line of code sends this message Cannot create asynchronous query while in a write transaction and then write a stable demo to reproduce it. I may fix the problems in my code by comparing the demo with my code.

Here's my code in thread com.?????.???.realm.
Thanks!

- (void)updateResourceLogSuccess:(NSArray<BKLResourceViewLogRO *> *)results {
    [self changeLogs:results toStatus:BKLResourceViewLogROFinish];

    RLMResults<BKLResourceViewLogRO *> *finishResults = [BKLResourceViewLogRO objectsWhere:@"status = %ld", BKLResourceViewLogROFinish];
    if (finishResults.count > 0) {
        [[RLMRealm defaultRealm] transactionWithBlock:^{
            [[RLMRealm defaultRealm] deleteObjects:finishResults];
        }];
    }
}


- (void)changeLogs:(NSArray<BKLResourceViewLogRO *> *)logs
          toStatus:(BKLResourceViewLogROStatus)status {
    if (logs.count == 0) {
        return;
    }

    RLMRealm *realm = [RLMRealm defaultRealm];
    [realm beginWriteTransaction];

    for (BKLResourceViewLogRO *log in logs) {
        if (log.invalidated) {
            NSAssert(log.invalidated, @"Oops!");
            [realm cancelWriteTransaction];
            return;
        }

        log.status = status;
    }

    [realm commitWriteTransaction];
}

Version of Realm and Tooling

ProductName:    Mac OS X
ProductVersion: 10.12
BuildVersion:   16A323

/Applications/Xcode.app/Contents/Developer
Xcode 8.0
Build version 8A218a

/usr/local/bin/pod
1.0.1


/bin/bash
GNU bash, version 3.2.57(1)-release (x86_64-apple-darwin16)

/usr/local/bin/carthage
0.18
github "realm/realm-cocoa" "v2.0.2"

/usr/bin/git
git version 2.8.4 (Apple Git-73)
O-Community P-2-Expected Reproduction-Required T-Bug

Most helpful comment

Oh. My bad! I fixed it by storing realm in a local variable. Thanks!

Edit: I wrote this function in my Realm extension to handle this better:

func write(withoutNotifying: [NotificationToken], f: (Realm) -> Void) throws {
    beginWrite()
    f(self)
    try commitWrite(withoutNotifying: withoutNotifying)
}    

All 22 comments

I use Fabric to collect crash data. Fabric treats another crash with a different stack info as the same issue as the crash above.

Possible related threads:

Fatal Exception: realm::InvalidTransactionException: Cannot create asynchronous query while in a write transaction



Crashed: com.twitter.crashlytics.ios.exception
0  ??????                         0x100fcfbac CLSProcessRecordAllThreads + 9529772
1  ??????                         0x100fcfbac CLSProcessRecordAllThreads + 9529772
2  ??????                         0x100fcfa68 CLSProcessRecordAllThreads + 9529448
3  ??????                         0x100fc0228 CLSHandler + 9465896
4  ??????                         0x100fcdc80 __CLSExceptionRecord_block_invoke + 9521792
5  libdispatch.dylib              0x180ad947c _dispatch_client_callout + 16
6  libdispatch.dylib              0x180ae4728 _dispatch_barrier_sync_f_invoke + 100
7  ??????                         0x100fcd724 CLSExceptionRecord + 9520420
8  ??????                         0x100fcd254 CLSTerminateHandler() + 9519188
9  libc++abi.dylib                0x1806e6f44 std::__terminate(void (*)()) + 16
10 libc++abi.dylib                0x1806e6b10 __cxa_rethrow + 144
11 libobjc.A.dylib                0x1806f4120 objc_exception_rethrow + 44
12 CoreFoundation                 0x180f6ccf8 CFRunLoopRunSpecific + 552
13 GraphicsServices               0x182854088 GSEventRunModal + 180
14 UIKit                          0x186256088 UIApplicationMain + 204
15 ??????                         0x100163ad0 main (main.m:14)
16 libdispatch.dylib              0x180b0a8b8 (Missing)


RLMRealm notification listener
0  libsystem_kernel.dylib         0x180c11528 kevent + 8
1  Realm                          0x1018bd520 realm::_impl::ExternalCommitHelper::listen() (external_commit_helper.cpp:199)
2  Realm                          0x1018be5e0 std::__1::__async_func<realm::_impl::ExternalCommitHelper::ExternalCommitHelper(realm::_impl::RealmCoordinator&)::$_0>::operator()() (future:2341)
3  Realm                          0x1018be568 std::__1::__async_assoc_state<void, std::__1::__async_func<realm::_impl::ExternalCommitHelper::ExternalCommitHelper(realm::_impl::RealmCoordinator&)::$_0> >::__execute() (future:1032)
4  Realm                          0x1018be730 std::__1::__thread_proxy<std::__1::tuple<void (std::__1::__async_assoc_state<void, std::__1::__async_func<realm::_impl::ExternalCommitHelper::ExternalCommitHelper(realm::_impl::RealmCoordinator&)::$_0> >::*)(), std::__1::__async_assoc_state<void, std::__1::__async_func<realm::_impl::ExternalCommitHelper::ExternalCommitHelper(realm::_impl::RealmCoordinator&)::$_0> >*> >(void*, void*) (memory:2525)
5  libsystem_pthread.dylib        0x180cf3b28 _pthread_body + 156
6  libsystem_pthread.dylib        0x180cf3a8c _pthread_body + 154
7  libsystem_pthread.dylib        0x180cf1028 thread_start + 4


com.?????.???.Realm
0  libsystem_kernel.dylib         0x180c27f6c __psynch_mutexwait + 8
1  libsystem_pthread.dylib        0x180cf639c _pthread_mutex_lock_wait + 96
2  Realm                          0x101a3d844 realm::SharedGroup::do_begin_write() + 44
3  Realm                          0x1019758f4 realm::_impl::transaction::begin(realm::SharedGroup&, realm::BindingContext*, realm::SchemaMode) (group_shared.hpp:968)
4  Realm                          0x101960828 -[RLMRealm beginWriteTransaction] (RLMRealm.mm:410)
5  ??????                         0x100473c6c static BKLAudioVideoPlayPointRO.(savePoint(forResourceModel : BKLResourceModel, historyPlayTime : Float) -> ()).(closure #1) (BKLAudioVideoPlayPointRO+Helper.swift:22)
6  libswiftObjectiveC.dylib       0x1025e9854 _TF10ObjectiveC15autoreleasepoolFFT_T_T_ + 48
7  libdispatch.dylib              0x180ae32d0 _dispatch_block_async_invoke_and_release + 752
8  libdispatch.dylib              0x180ad947c _dispatch_client_callout + 16
9  libdispatch.dylib              0x180ae54c0 _dispatch_queue_drain + 864
10 libdispatch.dylib              0x180adcf80 _dispatch_queue_invoke + 464
11 libdispatch.dylib              0x180ae7390 _dispatch_root_queue_drain + 728
12 libdispatch.dylib              0x180ae70b0 _dispatch_worker_thread3 + 112
13 libsystem_pthread.dylib        0x180cf1470 _pthread_wqthread + 1092
14 libsystem_pthread.dylib        0x180cf1020 start_wqthread + 4

And the code:

extension BKLAudioVideoPlayPointRO {

    class func savePoint(forResourceModel resourceModel: BKLResourceModel, historyPlayTime: Float) {
        Dispatch.excute(in: BooklnQueue.realm) {
            let realm = RLMRealm.default()
            realm.beginWriteTransaction()
            let object = BKLAudioVideoPlayPointRO.resourceModelTransformRealmRO(resourceModel, historyPlayTime: historyPlayTime)
            realm.addOrUpdate(object)
            try! realm.commitWriteTransaction()
        }
    }

}

Thanks very much.

This exception is thrown when adding a notification block from within a write transaction. Do you call addNotificationBlock() from anywhere in your code?

@jpsim I think it's not the case you mentioned.

I tried code below with a addNotificationBlock in a transaction. And it does crash as expected.

    [[RLMRealm defaultRealm] beginWriteTransaction];

    BKLXxxRO *object = [[BKLXxxRO alloc] initWithString:@"aa"];
    [[RLMRealm defaultRealm] addObject:object];

    RLMResults *allObjects = [BKLXxxRO allObjects];
    self.debugToken = [allObjects addNotificationBlock:^(RLMResults * _Nullable results, RLMCollectionChange * _Nullable change, NSError * _Nullable error) {

    }];

    [[RLMRealm defaultRealm] commitWriteTransaction];

The crash stack has something like -[RLMResults addNotificationBlock:] (RLMResults.mm:435).

Thread 0 name:  Dispatch queue: com.apple.main-thread
Thread 0 Crashed:
0   libsystem_kernel.dylib          0x0000000185f82014 __pthread_kill + 8
1   libsystem_pthread.dylib         0x0000000186049460 pthread_kill + 112
2   libsystem_c.dylib               0x0000000185ef6490 __abort + 144
3   libsystem_c.dylib               0x0000000185ef6400 __abort + 0
4   libc++abi.dylib                 0x00000001859c12d4 __cxa_bad_cast + 0
5   libc++abi.dylib                 0x00000001859deca8 default_terminate_handler() + 280
6   libobjc.A.dylib                 0x00000001859ec860 _objc_terminate() + 152
7   ??????                          0x000000010155d664 CLSTerminateHandler() + 332
8   libc++abi.dylib                 0x00000001859db66c std::__terminate(void (*)()) + 16
9   libc++abi.dylib                 0x00000001859daf84 __cxxabiv1::exception_cleanup_func(_Unwind_Reason_Code, _Unwind_Exception*) + 0
10  Realm                           0x00000001030f1310 realm::Results::prepare_async() (results.cpp:534)
11  Realm                           0x00000001030f1690 realm::Results::add_notification_callback(realm::CollectionChangeCallback) (memory:4289)
12  Realm                           0x0000000103105754 RLMNotificationToken* RLMAddNotificationBlock<realm::Results>(objc_object*, realm::Results&, void (objc_object*, RLMCollectionChange*, NSError*) block_pointer, bool) (RLMCollection.mm:339)
13  Realm                           0x000000010317d2e8 -[RLMResults addNotificationBlock:] (RLMResults.mm:435)
14  ??????                          0x000000010018ac4c -[BKLResourceViewLogManager updateResourceLogSuccess:] (BKLResourceViewLogManager.m:146)
15  ??????                          0x000000010018a8b8 __58-[BKLResourceViewLogManager uploadResourceLogWithResults:]_block_invoke (BKLResourceViewLogManager.m:128)
16  ??????                          0x0000000100d58b98 -[YTKNetworkAgent handleRequestResult:] (YTKNetworkAgent.m:246)
17  ??????                          0x0000000100d59684 __89-[YTKNetworkAgent requestOperationWithHTTPMethod:requestSerializer:URLString:parameters:]_block_invoke.240 (YTKNetworkAgent.m:303)
18  ??????                          0x0000000100920c78 __64-[AFHTTPRequestOperation setCompletionBlockWithSuccess:failure:]_block_invoke.49 (AFHTTPRequestOperation.m:138)
19  libdispatch.dylib               0x0000000185e3d200 _dispatch_call_block_and_release + 24
20  libdispatch.dylib               0x0000000185e3d1c0 _dispatch_client_callout + 16
21  libdispatch.dylib               0x0000000185e41b30 _dispatch_main_queue_callback_4CF + 428
22  CoreFoundation                  0x0000000186f61f2c __CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE__ + 12
23  CoreFoundation                  0x0000000186f5fb18 __CFRunLoopRun + 1660
24  CoreFoundation                  0x0000000186e8e048 CFRunLoopRunSpecific + 444
25  GraphicsServices                0x0000000188911198 GSEventRunModal + 180
26  UIKit                           0x000000018ce67818 -[UIApplication _run] + 684
27  UIKit                           0x000000018ce62550 UIApplicationMain + 208
28  ??????                          0x00000001001fbe3c main (main.m:14)
29  libdyld.dylib                   0x0000000185e705b8 start + 4

But I don't see any addNotificationBlock message in my own crashes. Is there any other clue?

Just out of curiosity, what happens when you make a new query from scratch in your write transaction?

- (void)updateResourceLogSuccess:(NSArray<BKLResourceViewLogRO *> *)results {
    [self changeLogs:results toStatus:BKLResourceViewLogROFinish];

    RLMResults<BKLResourceViewLogRO *> *finishResults = [BKLResourceViewLogRO objectsWhere:@"status = %ld", BKLResourceViewLogROFinish];
    if (finishResults.count > 0) {
        [[RLMRealm defaultRealm] transactionWithBlock:^{
            [[RLMRealm defaultRealm] deleteObjects:[BKLResourceViewLogRO objectsWhere:@"status = %ld", BKLResourceViewLogROFinish]];
        }];
    }
}

or if you trigger an access of one of the elements of the RLMResults prior to accessing it in the write transaction?

- (void)updateResourceLogSuccess:(NSArray<BKLResourceViewLogRO *> *)results {
    [self changeLogs:results toStatus:BKLResourceViewLogROFinish];

    RLMResults<BKLResourceViewLogRO *> *finishResults = [BKLResourceViewLogRO objectsWhere:@"status = %ld", BKLResourceViewLogROFinish];
    if (finishResults.firstObject != nil) {
        [[RLMRealm defaultRealm] transactionWithBlock:^{
            [[RLMRealm defaultRealm] deleteObjects:finishResults];
        }];
    }
}

Thank you so much @jpsim

I'll try this code even though I don't quite understand.

    [[RLMRealm defaultRealm] transactionWithBlock:^{
        RLMResults<BKLResourceViewLogRO *> *finishResults = [BKLResourceViewLogRO objectsWhere:@"status = %ld", BKLResourceViewLogROFinish];
        [[RLMRealm defaultRealm] deleteObjects:finishResults];
    }];

Also I wrote some demo code like below and run many times. It worked fine.

    RLMResults<BKLResourceViewLogRO *> *finishResults = [BKLResourceViewLogRO objectsWhere:@"status = %ld", BKLResourceViewLogROFinish];
    [[RLMRealm defaultRealm] transactionWithBlock:^{
        [[RLMRealm defaultRealm] deleteObjects:finishResults];
    }];

Maybe the stack info is not so clear. I tried hard to find problems in my code but failed.
Instead of rewriting the code right now, I'll collect more information. I found that HockeyApp may be the best crash tool and I decide to give it a try.
I'll give feedback after releasing a new version of my app in a week.

I suspect this might be a bug in Realm where if the count of an RLMResults is accessed from outside a write transaction, then its contents is accessed from within a write transaction before the results can be asynchronously calculated, this exception is thrown. We'll need to investigate more to know if this is actually the case.

@jpsim
This crash doesn't happen any more after I tried if (finishResults.count > 0) { that you told me.
Should I close this issue now?

No, let's keep this open as I suspect this is actually a bug, but I'm glad you were able to work around it @jaybowong!

Any chance you can provide us with a sample project that reproduces this exception?

I'm getting this exception, apparently because commitWrite doesn't end the transaction:

if let notificationToken = notificationToken {
    guard !inventory.isInvalidated else {
        return
    }
    print("is in transaction: \(inventory.realm?.isInWriteTransaction)") // the second time when this block is executed, this is true
    inventory.realm?.beginWrite() // crash (second time)
    inventory.realm?.delete(inventory)
    try! inventory.realm?.commitWrite(withoutNotifying: [notificationToken])
}

If I replace beginWrite and commitWrite with write block it doesn't crash

guard !inventory.isInvalidated else {
    return
}
print("is in transaction: \(inventory.realm?.isInWriteTransaction)") // always false
try! inventory.realm?.write { // always works
    inventory.realm?.delete(inventory)
}

After you delete inventory, inventory.realm will be nil and inventory.realm?.commitWrite() is a no-op as a result.

Oh. My bad! I fixed it by storing realm in a local variable. Thanks!

Edit: I wrote this function in my Realm extension to handle this better:

func write(withoutNotifying: [NotificationToken], f: (Realm) -> Void) throws {
    beginWrite()
    f(self)
    try commitWrite(withoutNotifying: withoutNotifying)
}    

So. Hello everyone!
Have updated Realm from 2.0.3 to 2.1.1 and constantly get crash.

dispatch_async(dispatch_get_main_queue(), ^
{
RLMRealm* realm = [RLMRealm defaultRealm];
user = [User objectForPrimaryKey: jId];
[realm beginWriteTransaction];

if ( ! user )
{
user = [[User alloc] init];
user.jId = jId;
[realm addObject: user];
}

[user updateDataWithDictionary: dictionary];
[realm commitWriteTransaction];

[user.realm transactionWithBlock: ^
{
...
}];
});

And one new example:

try? realm.write({
itemsToken = items.addNotificationBlock{}
})

This is just example of logic. In write transaction I change the property that trigger some logic with addNotificationBlock.

I am experiencing this issue. I can't seem to have found a way to reproduce it.

Is there any way I can help getting to the bottom of this?

I do have something like:

[realm beginWriteTransaction];
Objects *objs = [self allObjects];
...
[realm commitTransaction];

It truly has a query inside the write transactions, but it doesn't crash all the times

I have gotten a few more crashlogs about this.

From the crash logs it appears that the problem occurs when changes are being made that fire change notifications to collections. The problem seems to me, is that those changes are being fired before from within the transaction.

I can confirm to you that I am not adding notification blocks from within write transactions, but I am surely making changes/deleting objects that were in collections that have notification blocks adhered to them.

@jpsim is this issue being tracked here? or on #4515?

My app is crashing a lot due to this issue. I've tried to remove all queries from my transactions, but it still crashes :(.

The issue tracked here appears to be distinct from the one tracked in #4515. The best way to help us fix this is to show us how we can reproduce it.

Seems like you're hitting this quite a bit, and therefore are in the best position to show us how we can trigger it ourselves.

I've opened issue #4671 which is the description of my problem. Whatever code that I have that can possibly reproduce my issue.

I solved this.

Hello Guys, I recently experimented this issue after update Realm, and I figured out I was posting a notification: NotificationCenter.default.post(name: "notificationName", object: nil) just withing a notification block, and here was my code:

notificationToken = results.addNotificationBlock { [weak self] (changes: RealmCollectionChange) in
            guard let tableView = self?.tableView else { return }
            switch changes {

            case .initial:

                tableView.reloadData()
                break
            case .update(_, _, _, _):

                NotificationCenter.default.post(name: "notificationName", object: nil)
                break

            case .error(let error):

                fatalError("\(error)")

                break
            }
        }

and, I was subscribed to hear that notification in order to make a query of the same kind of objects being updated. I removed that bunch of code and the issue was solved. I hope this can help you.

@jpsim In my case the write transaction is in a completely different thread (processing incoming response from an API call) while the UI initialize itself at the same time (trying to add notify blocks for updates).

Is this a bug or a limitation of Realm?
This method cannot be called during a write transaction, or when the containing Realm is read-only. But I assumed it was relevant for inside the block

Multiple write blocks each other (to avoid this issue) but it seems Realm is missing some lock mechanism to hold off on addNotificationBlock until it can interleave within the write operations queue.

isInWriteTransaction gives a flag of when it is safe to call addNotificationBlock - but there should be a more automatic (and safer) way to queue adding of Notification Blocks IMHO


In any case, I was able to reproduce this issue in my code constantly with the following setup:

There's a write operation happening in one thread and your code is trying to create a notification block in another thread while the write operation is still running the exception will rise.

Each thread has it own let realm = try! Realm()

The write thread is using try! realm.write { } block while the read operation has simply queried using realm.objects(SomeRealmObject.self) and then tried to execute addNotificationBlock on the result of that.

after upgrading to 2.6.2 (from 1.1.0) I see same crash in fabric

Cannot create asynchronous query while in a write transaction

Fatal Exception: RLMException
0  CoreFoundation                 0x186596fd8 __exceptionPreprocess
1  libobjc.A.dylib                0x184ff8538 objc_exception_throw
2  Realm                          0x100d1c294 (Missing)
3  Realm                          0x100d1c558 (Missing)
4  Realm                          0x100d1c51c (Missing)
5  MyApp                          0x1001194b0 -[MMRealmServiceBase performSyncTransactionBlock:] (MMRealmServiceBase.m:66)
6  MyApp                          0x1001b47f4 -[MMUserServiceImplementation changeSetNumber:forRake:] (MMUserServiceImplementation.m:199)
7  MyApp                          0x100167d54 -[MMJoinJourneyInteractor changeSetNumber:forRake:] (MMJoinJourneyInteractor.m:232)
8  MyApp                          0x1001627b0 -[MMJoinJourneyPresenter didChangeSetNumber:forRake:] (MMJoinJourneyPresenter.m:111)
9  MyApp                          0x10016f0cc -[MMJoinJourneyViewController journeyItemDidUpdateSetNumber:forRake:] (MMJoinJourneyViewController.m:182)
10 MyApp                          0x1000b4248 -[MMJourneyItemViewCell actionEventSetNumber] (MMJourneyItemViewCell.m:152)
11 MyApp                          0x1000b43d4 -[MMJourneyItemViewCell textFieldDidEndEditing:] (MMJourneyItemViewCell.m:165)
12 UIKit                          0x18c7edc08 -[UITextField _resignFirstResponder]
13 UIKit                          0x18c7c4bcc -[UIResponder _finishResignFirstResponder]
14 UIKit                          0x18d125e80 -[UITextField _finishResignFirstResponder]
15 UIKit                          0x18c7693b0 -[UIResponder resignFirstResponder]
16 UIKit                          0x18c7ed814 -[UITextField resignFirstResponder]
17 UIKit                          0x18c84351c -[UIView(UITextField) endEditing:]
18 MyApp                          0x100140220 -[MMPushAnimator animateTransition:] (MMNavigationController.m:27)
19 UIKit                          0x18c85bca0 -[UINavigationController _startCustomTransition:]
20 UIKit                          0x18c775c4c -[UINavigationController _startDeferredTransitionIfNeeded:]
21 UIKit                          0x18c7758b4 -[UINavigationController __viewWillLayoutSubviews]
22 UIKit                          0x18c775818 -[UILayoutContainerView layoutSubviews]
23 UIKit                          0x18c6bc158 -[UIView(CALayerDelegate) layoutSublayersOfLayer:]
24 QuartzCore                     0x1898ac274 -[CALayer layoutSublayers]
25 QuartzCore                     0x1898a0de8 CA::Layer::layout_if_needed(CA::Transaction*)
26 QuartzCore                     0x1898a0ca8 CA::Layer::layout_and_display_if_needed(CA::Transaction*)
27 QuartzCore                     0x18981c360 CA::Context::commit_transaction(CA::Transaction*)
28 QuartzCore                     0x1898433c0 CA::Transaction::commit()
29 QuartzCore                     0x189843e8c CA::Transaction::observer_callback(__CFRunLoopObserver*, unsigned long, void*)
30 CoreFoundation                 0x1865449a0 __CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__
31 CoreFoundation                 0x186542628 __CFRunLoopDoObservers
32 CoreFoundation                 0x186542a74 __CFRunLoopRun
33 CoreFoundation                 0x186472d94 CFRunLoopRunSpecific
34 GraphicsServices               0x187edc074 GSEventRunModal
35 UIKit                          0x18c724130 UIApplicationMain
36 MyApp                          0x1001295fc main (main.m:14)
37 libdyld.dylib                  0x18548159c start

I do not see here addNotificationBlock inside and cannot reproduce till now, but it happens often in production version

by the way, I have reproduced our problem and cannot find the reason. realm inWriteTransaction returns NO just before beginTransaction, but than it fails with exception and realm inWriteTransaction in that moment returns YES. And there is no other threads with realm write transactions in that moment

Was this page helpful?
0 / 5 - 0 ratings