ReactiveX / RxSwift

Reactive Programming in Swift
MIT License
24.36k stars 4.17k forks source link

Crash with take(1) operator #1192

Closed tzm41 closed 7 years ago

tzm41 commented 7 years ago

Short description of the issue: I create an observable from Realm objects to retrieve one single object from the storage. Whenever I use .take(1) when I subscribe to it I get crash from RxSwift.

Expected outcome: Should go crash free.

What actually happens: Fatal error with warning Warning: Recursive call or synchronization error!, if I use .take(1). Of course it does not crash when I take the .take(1) out, but that would be a logical error in the code and result in undesired behaviors. Not totally sure it is Realm or RxSwift's issue?

Self contained code example that reproduces the issue:

Observable.collection(from: realm.objects(UserProfileRealmModel.self)).map { $0.first }.filterNil().map { $0 as! UserProfileModel }
    .observeOn(MainScheduler.instance)
    .take(1)
    .subscribe(onNext: { [unowned self] _ in
        self.goToMainView()
    }).addDisposableTo(mainViewDisposeBag)

Stack trace

#0  0x0000000111a6a7e0 in specialized _assertionFailure(StaticString, String, file : StaticString, line : UInt, flags : UInt32) -> Never ()
#1  0x000000010e37496f in rxFatalError(@autoclosure () -> String, file : StaticString, line : UInt) -> Never at /Users/Colin/Developer/learner-ios/Pods/RxSwift/RxSwift/Rx.swift:42
#2  0x000000010e1f54d3 in AnonymousObservableSink.on(Event<A.E>) -> () at /Users/Colin/Developer/learner-ios/Pods/RxSwift/RxSwift/Observables/Implementations/AnonymousObservable.swift:27
#3  0x000000010e1f600d in protocol witness for ObserverType.on(Event<A.E>) -> () in conformance <A where ...> AnonymousObservableSink<A> ()
#4  0x000000010e1f912e in partial apply ()
#5  0x000000010e1f80ef in AnyObserver.on(Event<A>) -> () at /Users/Colin/Developer/learner-ios/Pods/RxSwift/RxSwift/AnyObserver.swift:39
#6  0x000000010e1f8295 in protocol witness for ObserverType.on(Event<A.E>) -> () in conformance <A> AnyObserver<A> ()
#7  0x000000010e31d029 in ObserverType.onCompleted() -> () at /Users/Colin/Developer/learner-ios/Pods/RxSwift/RxSwift/ObserverType.swift:32
#8  0x000000010e1ad62b in static ObservableType<A where ...>.(collection(from : A.E, synchronousStart : Bool) -> Observable<A.E>).(closure #1).(closure #2) at /Users/Colin/Developer/learner-ios/Pods/RxRealm/Pod/Classes/RxRealm.swift:142
#9  0x000000010e1ba37b in partial apply for static ObservableType<A where ...>.(collection(from : A.E, synchronousStart : Bool) -> Observable<A.E>).(closure #1).(closure #2) ()
#10 0x000000010e1f3b98 in AnonymousDisposable.dispose() -> () at /Users/Colin/Developer/learner-ios/Pods/RxSwift/RxSwift/Disposables/AnonymousDisposable.swift:46
#11 0x000000010e1f3f65 in protocol witness for Disposable.dispose() -> () in conformance AnonymousDisposable ()
#12 0x000000010e33b8a4 in SinkDisposer.dispose() -> () at /Users/Colin/Developer/learner-ios/Pods/RxSwift/RxSwift/Observables/Implementations/Producer.swift:92
#13 0x000000010e33cdd5 in protocol witness for Disposable.dispose() -> () in conformance SinkDisposer ()
#14 0x000000010e33b8a4 in SinkDisposer.dispose() -> () at /Users/Colin/Developer/learner-ios/Pods/RxSwift/RxSwift/Observables/Implementations/Producer.swift:92
#15 0x000000010e33cdd5 in protocol witness for Disposable.dispose() -> () in conformance SinkDisposer ()
#16 0x000000010e397600 in SingleAssignmentDisposable.dispose() -> () at /Users/Colin/Developer/learner-ios/Pods/RxSwift/RxSwift/Disposables/SingleAssignmentDisposable.swift:71
#17 0x000000010e397f15 in protocol witness for Disposable.dispose() -> () in conformance SingleAssignmentDisposable ()
#18 0x000000010e209cfa in disposeAll(in : Bag<Disposable>) -> () at /Users/Colin/Developer/learner-ios/Pods/RxSwift/RxSwift/Extensions/Bag+Rx.swift:49
#19 0x000000010e28ac6e in CompositeDisposable.dispose() -> () at /Users/Colin/Developer/learner-ios/Pods/RxSwift/RxSwift/Disposables/CompositeDisposable.swift:112
#20 0x000000010e28d605 in protocol witness for Disposable.dispose() -> () in conformance CompositeDisposable ()
#21 0x000000010e33b8a4 in SinkDisposer.dispose() -> () at /Users/Colin/Developer/learner-ios/Pods/RxSwift/RxSwift/Observables/Implementations/Producer.swift:92
#22 0x000000010e33cdd5 in protocol witness for Disposable.dispose() -> () in conformance SinkDisposer ()
#23 0x000000010e33b8a4 in SinkDisposer.dispose() -> () at /Users/Colin/Developer/learner-ios/Pods/RxSwift/RxSwift/Observables/Implementations/Producer.swift:92
#24 0x000000010e33cdd5 in protocol witness for Disposable.dispose() -> () in conformance SinkDisposer ()
#25 0x000000010e33b8a4 in SinkDisposer.dispose() -> () at /Users/Colin/Developer/learner-ios/Pods/RxSwift/RxSwift/Observables/Implementations/Producer.swift:92
#26 0x000000010e33cdd5 in protocol witness for Disposable.dispose() -> () in conformance SinkDisposer ()
#27 0x000000010e33b8a4 in SinkDisposer.dispose() -> () at /Users/Colin/Developer/learner-ios/Pods/RxSwift/RxSwift/Observables/Implementations/Producer.swift:92
#28 0x000000010e33cdd5 in protocol witness for Disposable.dispose() -> () in conformance SinkDisposer ()
#29 0x000000010e39c2c8 in Sink.dispose() -> () at /Users/Colin/Developer/learner-ios/Pods/RxSwift/RxSwift/Observables/Implementations/Sink.swift:53
#30 0x000000010e3c4397 in TakeCountSink.on(Event<A.E>) -> () at /Users/Colin/Developer/learner-ios/Pods/RxSwift/RxSwift/Observables/Implementations/Take.swift:36
#31 0x000000010e3c4bad in protocol witness for ObserverType.on(Event<A.E>) -> () in conformance <A where ...> TakeCountSink<A> ()
#32 0x000000010e3190a1 in ObserveOnSerialDispatchQueueSink.(init(scheduler : SerialDispatchQueueScheduler, observer : A, cancel : Cancelable) -> ObserveOnSerialDispatchQueueSink<A>).(closure #1) at /Users/Colin/Developer/learner-ios/Pods/RxSwift/RxSwift/Observables/Implementations/ObserveOnSerialDispatchQueue.swift:38
#33 0x000000010e319398 in partial apply for ObserveOnSerialDispatchQueueSink.(init(scheduler : SerialDispatchQueueScheduler, observer : A, cancel : Cancelable) -> ObserveOnSerialDispatchQueueSink<A>).(closure #1) ()
#34 0x000000010e319e7e in thunk ()
#35 0x000000010e319f7d in partial apply for thunk ()
#36 0x000000010e2e13e1 in MainScheduler.scheduleInternal<A> (A, action : (A) -> Disposable) -> Disposable at /Users/Colin/Developer/learner-ios/Pods/RxSwift/RxSwift/Schedulers/MainScheduler.swift:51
#37 0x000000010e38861a in SerialDispatchQueueScheduler.schedule<A> (A, action : (A) -> Disposable) -> Disposable at /Users/Colin/Developer/learner-ios/Pods/RxSwift/RxSwift/Schedulers/SerialDispatchQueueScheduler.swift:92
#38 0x000000010e319c95 in ObserveOnSerialDispatchQueueSink.onCore(Event<A.E>) -> () at /Users/Colin/Developer/learner-ios/Pods/RxSwift/RxSwift/Observables/Implementations/ObserveOnSerialDispatchQueue.swift:49
#39 0x000000010e31c190 in ObserverBase.on(Event<A>) -> () at /Users/Colin/Developer/learner-ios/Pods/RxSwift/RxSwift/Observers/ObserverBase.swift:18
#40 0x000000010e31cb35 in protocol witness for ObserverType.on(Event<A.E>) -> () in conformance <A> ObserverBase<A> ()
#41 0x000000010e39bc00 in Sink.forwardOn(Event<A.E>) -> () at /Users/Colin/Developer/learner-ios/Pods/RxSwift/RxSwift/Observables/Implementations/Sink.swift:40
#42 0x000000010e2e2ef4 in MapSink.on(Event<A>) -> () at /Users/Colin/Developer/learner-ios/Pods/RxSwift/RxSwift/Observables/Implementations/Map.swift:27
#43 0x000000010e2e36dd in protocol witness for ObserverType.on(Event<A.E>) -> () in conformance <A, B where ...> MapSink<A, B> ()
#44 0x000000010e39bc00 in Sink.forwardOn(Event<A.E>) -> () at /Users/Colin/Developer/learner-ios/Pods/RxSwift/RxSwift/Observables/Implementations/Sink.swift:40
#45 0x000000010e2f3d7c in MergeSinkIter.on(Event<B.E>) -> () at /Users/Colin/Developer/learner-ios/Pods/RxSwift/RxSwift/Observables/Implementations/Merge.swift:243
#46 0x000000010e2f445d in protocol witness for ObserverType.on(Event<A.E>) -> () in conformance <A, B, C where ...> MergeSinkIter<A, B, C> ()
#47 0x000000010e2deb9d in Just.subscribe<A where ...> (A1) -> Disposable at /Users/Colin/Developer/learner-ios/Pods/RxSwift/RxSwift/Observables/Implementations/Just.swift:56
#48 0x000000010e2ef612 in MergeSink.subscribeInner(Observable<C.E>) -> () at /Users/Colin/Developer/learner-ios/Pods/RxSwift/RxSwift/Observables/Implementations/Merge.swift:315
#49 0x000000010e2eed44 in MergeSink.on(Event<A>) -> () at /Users/Colin/Developer/learner-ios/Pods/RxSwift/RxSwift/Observables/Implementations/Merge.swift:293
#50 0x000000010e2f477b in protocol witness for ObserverType.on(Event<A.E>) -> () in conformance <A, B, C where ...> MergeSink<A, B, C> ()
#51 0x000000010e39bc00 in Sink.forwardOn(Event<A.E>) -> () at /Users/Colin/Developer/learner-ios/Pods/RxSwift/RxSwift/Observables/Implementations/Sink.swift:40
#52 0x000000010e2e2ef4 in MapSink.on(Event<A>) -> () at /Users/Colin/Developer/learner-ios/Pods/RxSwift/RxSwift/Observables/Implementations/Map.swift:27
#53 0x000000010e2e36dd in protocol witness for ObserverType.on(Event<A.E>) -> () in conformance <A, B where ...> MapSink<A, B> ()
#54 0x000000010e39bc00 in Sink.forwardOn(Event<A.E>) -> () at /Users/Colin/Developer/learner-ios/Pods/RxSwift/RxSwift/Observables/Implementations/Sink.swift:40
#55 0x000000010e1f581e in AnonymousObservableSink.on(Event<A.E>) -> () at /Users/Colin/Developer/learner-ios/Pods/RxSwift/RxSwift/Observables/Implementations/AnonymousObservable.swift:39
#56 0x000000010e1f600d in protocol witness for ObserverType.on(Event<A.E>) -> () in conformance <A where ...> AnonymousObservableSink<A> ()
#57 0x000000010e1f912e in partial apply ()
#58 0x000000010e1f80ef in AnyObserver.on(Event<A>) -> () at /Users/Colin/Developer/learner-ios/Pods/RxSwift/RxSwift/AnyObserver.swift:39
#59 0x000000010e1f8295 in protocol witness for ObserverType.on(Event<A.E>) -> () in conformance <A> AnyObserver<A> ()
#60 0x000000010e31cef3 in ObserverType.onNext(A.E) -> () at /Users/Colin/Developer/learner-ios/Pods/RxSwift/RxSwift/ObserverType.swift:27
#61 0x000000010e1ad2b5 in static ObservableType<A where ...>.(collection(from : A.E, synchronousStart : Bool) -> Observable<A.E>).(closure #1).(closure #1) at /Users/Colin/Developer/learner-ios/Pods/RxRealm/Pod/Classes/RxRealm.swift:137
#62 0x000000010e1ba26b in partial apply for static ObservableType<A where ...>.(collection(from : A.E, synchronousStart : Bool) -> Observable<A.E>).(closure #1).(closure #1) ()
#63 0x000000010e1ab231 in thunk ()
#64 0x000000010e1ab312 in partial apply for thunk ()
#65 0x000000010ddb96f0 in Results.(addNotificationBlock((RealmCollectionChange<Results<A>>) -> ()) -> RLMNotificationToken).(closure #1) at /Users/Colin/Developer/learner-ios/Pods/RealmSwift/RealmSwift/Results.swift:377
#66 0x000000010ddb982e in partial apply for Results.(addNotificationBlock((RealmCollectionChange<Results<A>>) -> ()) -> RLMNotificationToken).(closure #1) ()
#67 0x000000010dd64c67 in thunk ()
#68 0x000000010d21c35e in RLMNotificationToken* RLMAddNotificationBlock<realm::Results>(objc_object*, realm::Results&, void (objc_object*, RLMCollectionChange*, NSError*) block_pointer, bool)::'lambda'(realm::CollectionChangeSet const&, std::exception_ptr)::operator()(realm::CollectionChangeSet const&, std::exception_ptr) const at /Users/Colin/Developer/learner-ios/Pods/Realm/Realm/RLMCollection.mm:345
#69 0x000000010d21b919 in realm::CollectionChangeCallback::Impl<RLMNotificationToken* RLMAddNotificationBlock<realm::Results>(objc_object*, realm::Results&, void (objc_object*, RLMCollectionChange*, NSError*) block_pointer, bool)::'lambda'(realm::CollectionChangeSet const&, std::exception_ptr)>::after(realm::CollectionChangeSet const&) at /Users/Colin/Developer/learner-ios/Pods/Realm/include/collection_notifications.hpp:157
#70 0x000000010d0c02e7 in realm::CollectionChangeCallback::after(realm::CollectionChangeSet const&) at /Users/Colin/Developer/learner-ios/Pods/Realm/include/collection_notifications.hpp:122
#71 0x000000010d0c01fc in auto realm::_impl::CollectionNotifier::after_advance()::$_9::operator()<std::__1::unique_lock<std::__1::mutex>, realm::_impl::CollectionNotifier::Callback>(std::__1::unique_lock<std::__1::mutex>&, realm::_impl::CollectionNotifier::Callback&) const at /Users/Colin/Developer/learner-ios/Pods/Realm/Realm/ObjectStore/src/impl/collection_notifier.cpp:327
#72 0x000000010d07c3eb in void realm::_impl::CollectionNotifier::for_each_callback<realm::_impl::CollectionNotifier::after_advance()::$_9>(realm::_impl::CollectionNotifier::after_advance()::$_9&&) at /Users/Colin/Developer/learner-ios/Pods/Realm/Realm/ObjectStore/src/impl/collection_notifier.cpp:368
#73 0x000000010d07c15c in realm::_impl::CollectionNotifier::after_advance() at /Users/Colin/Developer/learner-ios/Pods/Realm/Realm/ObjectStore/src/impl/collection_notifier.cpp:316
#74 0x000000010d08137f in realm::_impl::NotifierPackage::after_advance() at /Users/Colin/Developer/learner-ios/Pods/Realm/Realm/ObjectStore/src/impl/collection_notifier.cpp:475
#75 0x000000010d5731eb in void (anonymous namespace)::advance_with_notifications<realm::_impl::transaction::advance(std::__1::unique_ptr<realm::SharedGroup, std::__1::default_delete<realm::SharedGroup> > const&, realm::BindingContext*, realm::_impl::NotifierPackage&)::$_0>(realm::BindingContext*, std::__1::unique_ptr<realm::SharedGroup, std::__1::default_delete<realm::SharedGroup> > const&, realm::_impl::transaction::advance(std::__1::unique_ptr<realm::SharedGroup, std::__1::default_delete<realm::SharedGroup> > const&, realm::BindingContext*, realm::_impl::NotifierPackage&)::$_0&&, realm::_impl::NotifierPackage&) at /Users/Colin/Developer/learner-ios/Pods/Realm/Realm/ObjectStore/src/impl/transact_log_handler.cpp:675
#76 0x000000010d57283f in realm::_impl::transaction::advance(std::__1::unique_ptr<realm::SharedGroup, std::__1::default_delete<realm::SharedGroup> > const&, realm::BindingContext*, realm::_impl::NotifierPackage&) at /Users/Colin/Developer/learner-ios/Pods/Realm/Realm/ObjectStore/src/impl/transact_log_handler.cpp:698
#77 0x000000010d169406 in realm::_impl::RealmCoordinator::advance_to_ready(realm::Realm&) at /Users/Colin/Developer/learner-ios/Pods/Realm/Realm/ObjectStore/src/impl/realm_coordinator.cpp:781
#78 0x000000010d4c3eb1 in realm::Realm::notify() at /Users/Colin/Developer/learner-ios/Pods/Realm/Realm/ObjectStore/src/shared_realm.cpp:665
#79 0x000000010d5c7767 in realm::_impl::WeakRealmNotifier::Callback::operator()() const at /Users/Colin/Developer/learner-ios/Pods/Realm/Realm/ObjectStore/src/impl/weak_realm_notifier.cpp:42
#80 0x000000010d5c8ec4 in realm::util::EventLoopSignal<realm::_impl::WeakRealmNotifier::Callback>::EventLoopSignal(realm::_impl::WeakRealmNotifier::Callback&&)::'lambda'(void*)::operator()(void*) const at /Users/Colin/Developer/learner-ios/Pods/Realm/include/util/apple/event_loop_signal.hpp:37
#81 0x000000010d5c8e68 in realm::util::EventLoopSignal<realm::_impl::WeakRealmNotifier::Callback>::EventLoopSignal(realm::_impl::WeakRealmNotifier::Callback&&)::'lambda'(void*)::__invoke(void*) at /Users/Colin/Developer/learner-ios/Pods/Realm/include/util/apple/event_loop_signal.hpp:36
#82 0x000000010b6d5c01 in __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ ()
#83 0x000000010b6bb058 in __CFRunLoopDoSources0 ()
#84 0x000000010b6ba5ff in __CFRunLoopRun ()
#85 0x000000010b6ba016 in CFRunLoopRunSpecific ()
#86 0x00000001141e1a24 in GSEventRunModal ()
#87 0x000000010ea7a0d4 in UIApplicationMain ()
#88 0x000000010903f992 in main at /Users/Colin/Developer/learner-ios/learner-ios/AppDelegate.swift:24
#89 0x000000011237a65d in start ()
#90 0x000000011237a65d in start ()

RxSwift/RxCocoa/RxBlocking/RxTest version/commit

RxSwift 3.4.0

Platform/Environment

How easy is to reproduce? (chances of successful reproduce after running the self contained code)

Xcode version:

8.3.1

Installation method:

I have multiple versions of Xcode installed: (so we can know if this is a potential cause of your issue)

Level of RxSwift knowledge: (this is so we can understand your level of knowledge and formulate the response in an appropriate manner)

kzaher commented 7 years ago

Hi @tzm41 ,

I believe this is a bug with RxRealm. This line should be deleted.

https://github.com/RxSwiftCommunity/RxRealm/blob/master/Pod/Classes/RxRealm.swift#L142

And all other observer.onCompleted calls in dispose methods, like

https://github.com/RxSwiftCommunity/RxRealm/blob/master/Pod/Classes/RxRealm.swift#L204

Could you please make a PR to RxRealm?

tzm41 commented 7 years ago

Ahhhhh very nice catch! I will make a PR for them. Thanks so much!

tzm41 commented 7 years ago

By the way, do you know why causes the recursion? In our own code, we do not call complete on the observer for the dispose action.

kzaher commented 7 years ago

The lines I've just told you about probably cause it, unless there is also some other bug.

tzm41 commented 7 years ago

Right, but why would calling on complete of the observer cause recursion?

kzaher commented 7 years ago

First element ->onNext -> take 1 causes disposal as a result -> onCompleted is attempted.

tzm41 commented 7 years ago

Thanks for explaining.