-
Notifications
You must be signed in to change notification settings - Fork 7.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Android] Problems with HandlerThreadScheduler since 0.19.1 #1407
Comments
So, one thing I discovered is that in this particular case, the action we execute is actually quite fast for small amounts of data and we forgot to actually schedule it on a background thread (so we didn't notice it was running on the main UI thread). i.e. we didn't I wonder if there's a timing issue or other glitch when observing something on the same thread you're already on? I can't reproduce it locally, unfortunately. |
@mttkay I saw your description above which made me curious. After looking into OperatorObserveOn and It's interaction with HandlerThreadScheduler here is what I found:
So with the code below: final Subscription subscription = Observable.from(new Object()) If ObserveOnSubscriber.onNext(..) is called and an InnerHandlerThreadScheduler.schedule(..) call puts a ScheduledAction in the Loopers queue, when you call subscription.unsubscribe(); it will also queue another Runnable behind the one which will call onNext(..) on your subscriber. So you end up with something like this in the Looper's MessageQueue Note that that happens since even though you are calling unsubscribe from the main thread, ScheduledUnsubscribe.unsubscribe() queues the subscribe() for the worker; see below: @OverRide So when your call to unsubscribe() returns within onDestroyView() all pending Runnable instances in the queue will still be executed. It seems to me that within OperatorObserveOn.pollQueue() there should be a check for scheduledUnsubscribe.isUnsubscribed()? I am going to send a pull request with the fix for it today. Let me know your thoughts!? |
The problem is that an unsubscribe() call from downstream is not distinguished from upstream. The former should unsubscribe the worker and drop every queued event whereas an upstream unsubscribe - usually called due to an onError case - should let queued events including the final onError to be delivered before the worker is shut down. The problem is in L75: don't share the child subscriber's internal composite, but rather use child.add(new ObserveOnSubscriber(...)) near L56. |
@dpsm good find! I wasn't aware of
since the call to This also means that removing posted runnables in the subscription block is less effective than it could be. @akarnokd what do you mean with up- and downstream? |
@mttkay we have a fix to be merged soon that should implement the correct behaviour. See my comment above referring to the fix. |
@benjchristensen the fix for it is merged. @mttkay please verify with version 0.19.4 |
Thanks so much guys, I will see to release a new beta running on 0.19.4 |
Closing out. Please reopen or start a new issue if the fix did not work. |
We've put our app in beta recently, running RxJava 0.19.1. We're suddenly seeing problems with scheduling on the main thread, where notifications arrive even after unsubscribing from the observable. I suspect RxJava itself might be the cause here since the scheduler implementation changed in 0.19. I wanted to double check if anyone else is seeing this happen?
More specifically, what happens is that in a subscriber from which we unsubscribe in Fragment#onDestroyView, getView() returns null, crashing the app. This should never happen when unsubscribing before the views get destroyed, unless messages for some reason keep propagating to the subscriber. There had even been a fix committed recently that eagerly removes all pending Runnables from the handler's message looper upon unsubscription, so I wonder how this can even happen.
Unfortunately, these things are incredibly difficult to debug as they are usually timing issues. Some code extracts:
The text was updated successfully, but these errors were encountered: