-
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 HandlerThreadScheduler fix (closes #1241) #1242
Conversation
RxJava-pull-requests #1143 SUCCESS |
Thanks @vinc3m1 for debugging and fixing this. It looks like a correct change to me and the comparison with @zsxwing Since you've been involved with the Android code and schedulers, can you review this as well? @akarnokd Since you are involved in a review of schedulers right now, can you also glance at this? |
if (isUnsubscribed()) {
return;
} I think the above codes is necessary, or However, I think a better approach is if (innerSubscription.isUnsubscribed()) {
// don't schedule, we are unsubscribed
return Subscriptions.empty();
}
handler.postDelayed(runnable, unit.toMillis(delayTime));
Subscription s = Subscriptions.create(new Action0() {
@Override
public void call() {
handler.removeCallbacks(runnable);
}
});
innerSubscription.add(s);
return s; |
+1 to what @zsxwing proposed. The unsubscribed check should happen before the schedule, but not inside the runnable. I can make the appropriate changes to the PR. |
RxJava-pull-requests #1150 SUCCESS |
} | ||
|
||
}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you add the returned Subscription
to innerSubscription
? innerSubscription
also needs to be a CompositeSubscription
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hm, wouldn't that cause the original problem to occur again? If innerSubscription
gets unsubscribed, it would cancel the runnable, effectively doing the same thing as before this change.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think that's the expected behavior. If innerSubscription
gets unsubscribed, all scheduled actions should be cancelled. You can take a look at NewThreadScheduler.NewThreadWorker
. Could you test with NewThreadScheduler
to see if there is same issue?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I will try to run a test tomorrow but it's rather hard to reproduce as it requires the new thread to be slightly blocked. But I read the code from NewThreadExecutor and it doesn't cancel any scheduled tasks that I can tell. It does call executor.shutdown()
but that still executes all previously submitted tasks.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
NewThreadScheduler
uses executor.shutdown()
which allows already submitted tasks to run but prevents new tasks being scheduled. I think this is the wrong behavior there and I should have used executor.shutdownNow()
instead; a fix is underway. Since the Handler scheduler can't be stopped and thus stopping all tasks, you need to keep track of the worker's submitted tasks.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry, I should have typed EventLoopsScheduler.EventLoopWorker
I've looked at #1241 and it seems this is the artifact of the A possible fix would be for the |
What about if creating a new Subscription rather than chaining them here: https://github.com/Netflix/RxJava/blob/e6ae50b279b224d0560772e147e48397623b1693/rxjava-core/src/main/java/rx/operators/OperatorObserveOn.java#L68 ? |
@akarnokd's solution looks like it should work. Should I close this PR for now, or wait until you open a new one after the conflict is resolved? |
Since this PR just makes the issue happen less likely, I suppose this can be closed. Let's discuss further options in #1241 |
Some events are not delivered due to race condition around the check to
innerSubscription.isUnsubscribed()
in the posted runnable. It's currently possible for the Handler thread to be delayed enough that innerSubscription becomes unsubscribed, and causing the action not to run.After cross-checking the code with
NewThreadScheduler
, it seems that the expected behavior is to continue to run the action even if the inner/parent subscription is unsubscribed, and only stop when the outer subscription is unsubscribed (which is already happening withhandler.removeCallbacks(runnable)
).This fixes #1241.