-
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
Still problems with unsubscribed observables calling subscriber #1590
Comments
Correct that when
What are you referring to when you say "we unsubscribe immediately"? When going over async boundaries, such as If there is an operator/subscriber sensitive to possibly receiving What about this use case is so sensitive that it crashes? Can you provide more information on the use case so I can provide more concrete guidance? |
Thanks for clarifying. That's indeed a big issue on Android then. The problem is that unsubscribing from an observable as part of a (synchronous) life-cycle callback in Android must ensure that no more messages will arrive in the subscriber, since Android will do its clean up synchronously / immediately:
In the above code snippet, line 2 will always finish before line 1, since We can work around this with `OperatorConditionalBinding' which will ignore "out of band" messages that arrive after Android has released all views. I'm just not a fan of a defensive programming style, so I'm wondering if there's something that we can do to release subscribers immediately? |
Out of interest, why does Do you think it makes sense to add a new subscriber wrapper or base class which only forwards notifications if it's not unsubscribed from? |
@mttkay what if InnerHandlerThreadScheduler.schedule(..) checked the calling Looper against the one of it's internal Handler and invoke the action synchronously? That should turn the unsubscribe() sync when called from the Android UI thread! Let me know what you think, and I can put a quick patch together for that :) |
@dpsm I remember we tried that before, and it caused problems with recursive scheduling, resulting in stack overflows. The scheduler implementation has changed a few times though, so this might not be valid anymore. In fact this was attempted multiple times in different PRs. Some of the discussion you can find here: |
That said, there might be a case to be made for optimizing This problem goes well beyond a mere performance issue though, as it affects stability. |
@mttkay regarding recursive scheduling resulting in stack overflows, the provided Action should be responsible to break the recursion and avoid the stack overflow just like any recursive call should it not? I am not sure I understand the issue so please apologize if I am not following you :) Another alternative would be something like this: private ThreadLocal<Queue<Action0>> pendingActions = new ThreadLocal<Queue<Action0>>() {
@Override
protected Queue<Action0> initialValue() {
return new LinkedList<Action0>();
}
};
private ThreadLocal<Boolean> isCalling = new ThreadLocal<Boolean>() {
@Override
protected Boolean initialValue() {
return false;
}
};
@Override
public Subscription schedule(final Action0 action) {
final Looper handlerLooper = handler.getLooper();
if (Looper.myLooper() == handlerLooper) {
if (isCalling.get()) {
Queue<Action0> actions = pendingActions.get();
actions.add(action);
} else {
isCalling.set(true);
action.call();
Queue<Action0> actions = pendingActions.get();
while(!actions.isEmpty()) {
actions.poll().call();
}
isCalling.set(false);
}
return Subscriptions.empty();
} else {
return schedule(action, 0, TimeUnit.MILLISECONDS);
}
} thoughts? |
@mttkay thoughts on my comments above? Now that the Android project is somewhat independent, I'd be happy to help you and others setting up some roadmap of things we want to work on!? |
Hey @dpsm sorry for not staying on top of this, a bit swamped at the moment. We're still setting up RxAndroid and I'd like to get the build and project setup hurdles out of our feet first. Meanwhile I'd like to start by moving all RxAndroid related issues over to that project. Could you repost your proposal here? ReactiveX/RxAndroid#3 Then we can close this out and move the discussion over. Thanks! |
So, this is a follow-up to #1407, which I thought had been fixed at first, since the crashes were gone for one particular case, but now I see crashes in our app in different places that are exactly like this. This is with RxJava 0.20-RC3.
Not wanting to jump to conclusions, but as far as I understand the fix that went in we now make sure that as soon as the "downstream" subscriber (not sure if I'm getting the terminology right here) unsubscribes from the sequence, then we unsubscribe immediately. Is that correct?
I found another case where it's still not working, and it might be related to the use of the
cache
operator. Again, as in the other ticket subscription, this is a fragment subscribing to an observable inonViewCreated
, then unsubscribing inonDestroyView
, but still receiving calls to onNext, crashing it, since it will be detached from the window at that point in time.The only difference I could find to the case where it is now working is the use of the
cache
operator. Looking at it, it specifically says in the docs that the subscription returned from it will not unsubscribe from the source observable. Might that be the problem, i.e. will the fix that went in for #1407 not have any effect on this, as it attempted to fix it based on subscriber/subscription interaction?The text was updated successfully, but these errors were encountered: