realm-swift icon indicating copy to clipboard operation
realm-swift copied to clipboard

Crash in RLMObservationInfo::didChange(NSString*, NSKeyValueChange, NSIndexSet*) const (RLMObservation.hpp:116)

Open tspecht opened this issue 10 years ago • 23 comments

Hi!

I'm currently experiencing the following crash when trying to KVO observe objects invalidated property in my Realm. All the registering for the observations is done on the main thread. Any idea what could be wrong?

The crash specifically seems to occur when calling RLMRealm.defaultRealm().refresh() on the main thread and only in Release builds. Debug is running fine!

Thread : Crashed: com.apple.main-thread
0  MyApp                       0x0000000100718fc4 RLMObservationInfo::didChange(NSString*, NSKeyValueChange, NSIndexSet*) const (RLMObservation.hpp:116)
1  MyApp                       0x000000010071adb8 (anonymous namespace)::TransactLogHandler::notifyObservers() (RLMObservation.mm:473)
2  MyApp                       0x0000000100719e6c RLMAdvanceRead(realm::SharedGroup&, realm::History&, RLMSchema*) (RLMObservation.mm:503)
3  MyApp                       0x0000000100743d74 -[RLMRealm handleExternalCommit] (RLMRealm.mm:738)
4  MyApp                       0x00000001007488f0 -[RLMNotifier listen]::$_1::__invoke(void*) (RLMRealmUtil.mm:249)
5  CoreFoundation                 0x0000000182753f8c __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 24
6  CoreFoundation                 0x0000000182753230 __CFRunLoopDoSources0 + 264
7  CoreFoundation                 0x00000001827512e0 __CFRunLoopRun + 712
8  CoreFoundation                 0x000000018267cf74 CFRunLoopRunSpecific + 396
9  GraphicsServices               0x000000018c0d76fc GSEventRunModal + 168
10 UIKit                          0x000000018727ed94 UIApplicationMain + 1488
11 MyApp                       0x000000010014a398 main (main.m:33)
12 libdyld.dylib                  0x0000000194b1aa08 start + 4

tspecht avatar Sep 21 '15 08:09 tspecht

Sorry you've hit this! It's the first we hear of it.

I'll try reproducing this issue based on the information you've given us, but if you could send us a repro case along with steps to reproduce at [email protected], that would certainly accelerate the process.

jpsim avatar Sep 21 '15 16:09 jpsim

I'll try to come up with a sample project, but can't promise you anything. One more piece of information I was able to find out: I suppose this crash is just accuring on iOS 9? I really can't wrap my head around it, is it maybe some code stripping problem or has to do with the new bitcode feature introduced (although I have that turned of for my application in both Debug and Release)

tspecht avatar Sep 22 '15 06:09 tspecht

Okay I investigated this issue a little further today, it is also reproducible in iOS 8 (nonetheless, it seems to be occuring a little more often on iOS 9 but that really could be subjective). Unfortunately, I couldn't quite reproduce it easily in a sample project :/

tspecht avatar Sep 22 '15 16:09 tspecht

Might it be an issue that I'm trying to subscribe the invalidated property using ReactiveCocoa?

tspecht avatar Sep 22 '15 16:09 tspecht

No, that should definitely work fine.

tgoyne avatar Sep 22 '15 16:09 tgoyne

Subscribing via ReactiveCocoa shouldn't be making a difference here. Thanks for looking into creating a repro case for us. Keep us posted!

jpsim avatar Sep 22 '15 17:09 jpsim

Were you able to find anything out regarding this issue?

tspecht avatar Sep 22 '15 20:09 tspecht

I haven't been able to come up with a repro case, and the stack trace only really makes sense if something went wrong before the point where it actually crashes.

Are you observing invalidated over a multi-level keypath (and if so, are all of the things in the keypath realm objects?), or observing other properties on the same objects (and if so, might they be changing as well in the cases that lead to crashes?).

tgoyne avatar Sep 22 '15 20:09 tgoyne

Maybe it'll help if I shed some more light on what I'm up to :)

I currently have the problem, that some of the objects I display in a table view are getting deleted at some point and the table view not being reloaded fast enough. This then sometimes leads to crashes due to objects being "deleted or invalidated". Therefore I planned on observing the "invalidated" property to automatically reload the table and stop all other interaction with the objects until the dataset has been reloaded and is "save" again to access. Here's the code I use to do that

// Observe all the RLMObjects on their invalidation status
        for var i = 0; i < self.snipViewModel.numberOfItems(); i++ {
            if let realmObject = self.viewModel.itemAtIndex(i) as? RLMObject where !realmObject.invalidated {
                self.invalidatedDisposables.append(realmObject.rac_valuesForKeyPath("invalidated", observer: nil).subscribeNext({ [weak self] (x) -> Void in
                    if let invalidatedStatus = x as? Bool where invalidatedStatus == true {
                        self?.reloadData()
                        self?.reloadTable()
                    }
                }))
            }
        }

I store the disposables generated by ReactiveCocoa in an array to later get rid of them (e.g. when the table view is no longer displayed) so I don't get the updates anymore.

tspecht avatar Sep 22 '15 20:09 tspecht

Would any of you guys have another idea how I could solve my initial problem? I'm really desperate to find a solution for all of this ... :/

tspecht avatar Sep 23 '15 17:09 tspecht

Adding a notification block to the Realm which calls self.reloadData() should solve the same problem (unless you're doing write transactions on the main thread), but would have the downside of reloading for a lot of changes that don't need it.

tgoyne avatar Sep 23 '15 17:09 tgoyne

Yeah thats the problem, I guess that would be a little too much reloading overhead I would have with that approach :(

tspecht avatar Sep 23 '15 17:09 tspecht

@tspecht were you ever able to create a repro case for us to verify and troubleshoot? The invalidated key should be KVO-compliant.

jpsim avatar Sep 29 '15 19:09 jpsim

Closing due to lack of information to reproduce. Will reopen if we can obtain a repro case.

jpsim avatar Oct 05 '15 19:10 jpsim

I've got same crash.. It's really hard to replicate.. We've got ~200 crashes for last week with 163.6k daily users.. I can provide stacktrace if it helps, but it looks very similar to trace from above..

alexgarbarev avatar Aug 17 '16 19:08 alexgarbarev

@alexgarbarev could you please file a new issue with as much information as possible that could help us identify when this happens? It will be difficult to impossible for us to make progress on it until we can reproduce it ourselves thouhg.

jpsim avatar Aug 17 '16 23:08 jpsim

Ok, thanks @jpsim. Finally I've replicated that crash and did special github repo with demo: https://github.com/alexgarbarev/RealmKVOCrash/ It's pretty easy to replicate - you should delete object, while it observed by KVO. Should I still create a new issue? I think it's pretty much the same problem - same stacktrace.

alexgarbarev avatar Aug 18 '16 11:08 alexgarbarev

Thanks for the repro case. It's a fairly straightforward issue of that removing the last observer from within an observation results in the object that tracks the observer information being deleted while we're still using it.

tgoyne avatar Aug 18 '16 17:08 tgoyne

Thanks @tgoyne. I've tried master branch in my demo repository from above. Yep, that crash was fixed, but I was able to replicate another one. (see the screenshot) Crash

It looks like sometimes object deleted while another KVO notification isn't complete yet, so KVC call in change dictionary composing fails with exception:

*** Terminating app due to uncaught exception 'RLMException', reason: 'Object has been deleted or invalidated.'
*** First throw call stack:
(
    0   CoreFoundation                      0x000000010e2d2d85 __exceptionPreprocess + 165
    1   libobjc.A.dylib                     0x000000010dd46deb objc_exception_throw + 48
    2   RealmCrash                          0x000000010d0a70e3 _ZL17RLMVerifyAttachedP13RLMObjectBase + 83
    3   RealmCrash                          0x000000010d0aeb29 _ZL3getIN5realm10StringDataEET_P13RLMObjectBasem + 25
    4   RealmCrash                          0x000000010d0a5a8d _ZL12RLMGetStringP13RLMObjectBasem + 29
    5   RealmCrash                          0x000000010d0a6e67 ___ZL17RLMAccessorGetterP11RLMProperty15RLMAccessorCode_block_invoke_9 + 39
    6   Foundation                          0x000000010d8fa167 -[NSObject(NSKeyValueCoding) valueForKey:] + 280
    7   RealmCrash                          0x000000010d101f56 _ZZN18RLMObservationInfo11valueForKeyEP8NSStringENK3$_4clEv + 150
    8   RealmCrash                          0x000000010d101ca5 _ZN18RLMObservationInfo11valueForKeyEP8NSString + 1893
    9   RealmCrash                          0x000000010d0edbd5 -[RLMObjectBase valueForKey:] + 85
    10  Foundation                          0x000000010d8d8b0b NSKeyValueDidChangeBySetting + 65
    11  Foundation                          0x000000010d8d7e94 NSKeyValueDidChange + 301
    12  Foundation                          0x000000010d8dc70d -[NSObject(NSKeyValueObserverNotification) didChangeValueForKey:] + 118
    13  RealmCrash                          0x000000010d105967 _ZZNK18RLMObservationInfo9didChangeEP8NSString16NSKeyValueChangeP10NSIndexSetENK3$_3clIU8__strongP11objc_objectEEDaT_ + 39
    14  RealmCrash                          0x000000010d100f3e _ZNK18RLMObservationInfo7forEachIZNKS_9didChangeEP8NSString16NSKeyValueChangeP10NSIndexSetE3$_3EEvOT_ + 222
    15  RealmCrash                          0x000000010d100c8e _ZNK18RLMObservationInfo9didChangeEP8NSString16NSKeyValueChangeP10NSIndexSet + 222
    16  RealmCrash                          0x000000010d109d59 _ZZ12RLMDidChangeRKNSt3__16vectorIN5realm14BindingContext13ObserverStateENS_9allocatorIS3_EEEERKNS0_IPvNS4_IS9_EEEEENK3$_7clINS2_10ColumnInfoEEEDamRKT_P18RLMObservationInfo + 169
    17  RealmCrash                          0x000000010d10539e _ZN12_GLOBAL__N_17forEachIZ12RLMDidChangeRKNSt3__16vectorIN5realm14BindingContext13ObserverStateENS1_9allocatorIS5_EEEERKNS2_IPvNS6_ISB_EEEEE3$_7EEvRKS5_OT_ + 190
    18  RealmCrash                          0x000000010d104edd _Z12RLMDidChangeRKNSt3__16vectorIN5realm14BindingContext13ObserverStateENS_9allocatorIS3_EEEERKNS0_IPvNS4_IS9_EEEE + 605
    19  RealmCrash                          0x000000010d225452 _ZN12_GLOBAL__N_121RLMNotificationHelper10did_changeERKNSt3__16vectorIN5realm14BindingContext13ObserverStateENS1_9allocatorIS5_EEEERKNS2_IPvNS6_ISB_EEEE + 50
    20  RealmCrash                          0x000000010d265f42 _ZN12_GLOBAL__N_119TransactLogObserverC2IZN5realm5_impl11transaction7advanceERNS2_11SharedGroupEPNS2_14BindingContextENS2_10SchemaModeENS5_9VersionIDEE3$_0EES8_S6_OT_NS2_4util8OptionalIS9_EE + 1554
    21  RealmCrash                          0x000000010d26523d _ZN12_GLOBAL__N_119TransactLogObserverC1IZN5realm5_impl11transaction7advanceERNS2_11SharedGroupEPNS2_14BindingContextENS2_10SchemaModeENS5_9VersionIDEE3$_0EES8_S6_OT_NS2_4util8OptionalIS9_EE + 45
    22  RealmCrash                          0x000000010d2651fa _ZN5realm5_impl11transaction7advanceERNS_11SharedGroupEPNS_14BindingContextENS_10SchemaModeENS2_9VersionIDE + 138
    23  RealmCrash                          0x000000010d070bfc _ZN5realm5_impl16RealmCoordinator16advance_to_readyERNS_5RealmE + 1004
    24  RealmCrash                          0x000000010d2511a7 _ZN5realm5Realm6notifyEv + 359
    25  RealmCrash                          0x000000010d29623f _ZZN5realm5_impl17WeakRealmNotifierC1ERKNSt3__110shared_ptrINS_5RealmEEEbENK3$_0clEPv + 79
    26  RealmCrash                          0x000000010d2961e8 _ZZN5realm5_impl17WeakRealmNotifierC1ERKNSt3__110shared_ptrINS_5RealmEEEbEN3$_08__invokeEPv + 24
    27  CoreFoundation                      0x000000010e1f8301 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 17
    28  CoreFoundation                      0x000000010e1ee22c __CFRunLoopDoSources0 + 556
    29  CoreFoundation                      0x000000010e1ed6e3 __CFRunLoopRun + 867
    30  CoreFoundation                      0x000000010e1ed0f8 CFRunLoopRunSpecific + 488
    31  GraphicsServices                    0x0000000111aacad2 GSEventRunModal + 161
    32  UIKit                               0x000000010e688f09 UIApplicationMain + 171
    33  RealmCrash                          0x000000010cfbedbf main + 111
    34  libdyld.dylib                       0x000000010fd5c92d start + 1
    35  ???                                 0x0000000000000001 0x0 + 1
)

You can replicate that crash in the demo from above (I've updated realm and pushed updates). It happens time to time, but you'll face with that at least once per 3-4 runs

alexgarbarev avatar Aug 19 '16 13:08 alexgarbarev

Nice catch @alexgarbarev, let's reopen this.

jpsim avatar Aug 19 '16 19:08 jpsim

@tgoyne @jpsim UPD: this night spent not for nothing. Demo repo from above updated. Now it crashes in 100% runs for me. My observation is:

  • it crashes when main runloop paused (it happens during UITableView deceleration animation for example) and we update and delete same object. It looks like KVO-handling on main thread runs on invalidated object then (after main runloop resumed).

Please let me know if I can help with something.

alexgarbarev avatar Aug 20 '16 21:08 alexgarbarev

Is anyone actively working on this? We have a crash that seems to be related to this. What can I do to help get this figured out?

AnthonyMDev avatar Jul 10 '17 19:07 AnthonyMDev

No one is actively working on this AFAICT. You could debug the repro case shared above in order to determine what could fix it.

jpsim avatar Jul 10 '17 22:07 jpsim