-
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
ReplaySubject Race Condition #1147
Comments
It only happens very occasionally, but I reproduced it with this: @Test
public void testReplayAsCache() {
final List<Integer> expected = Arrays.asList(1);
for (int i = 0; i < 1000000; i++) {
TestSubscriber<Integer> ts = new TestSubscriber<Integer>();
Observable.just(1).subscribeOn(Schedulers.computation()).cache().subscribe(ts);
ts.awaitTerminalEvent();
ts.assertReceivedOnNext(expected);
ts.assertTerminalEvent();
}
} |
I think I found the issue: private static <T> int replayObserverFromIndex(History<T> history, int l, SubjectObserver<? super T> observer) {
while (l < history.index.get()) {
observer.onNext(history.list.get(l));
l++;
}
// --> if the emission and termination event happens here, the client won't receive the value but see the termination event only.
if (history.terminalValue.get() != null) {
if (l == 0) {
new IllegalStateException("Value expected here! Index: " + history.index.get()).printStackTrace();
}
history.terminalValue.get().accept(observer);
}
return l;
} |
Here is a ReplaySubject that did not fail for 100M iterations. It puts the terminal value onto the list. I haven't checked if performance is affected in some way. |
Awesome, thank you @akarnokd. You got a fix before I even had time to start digging in! It does indeed seem to have fixed it. I'm going to review it more closely and do performance testing, and if all looks well will move forward with this. Do you want to submit a PR with it so it's your merge? |
Done reviewing, the code looks good. Using the With this fix in place I can no longer see the Hystrix bug and the Rx unit test now always passes. PerformanceI tested performance using the already existing JMH tests:
Before
After
The changes slightly impact performance ... not really sure why ... but they are small. I'm going to proceed with this fix. |
I guess it is the small overhead from NotificationLite, perhaps adding final to History would enable some JVM optimizations. I'll have a look tomorrow. |
Thanks for your help on this, it made it possible to quickly release a fix for Hystrix: https://github.com/Netflix/Hystrix/releases/tag/1.3.16 |
A race condition with
ReplaySubject
was found while debugging a bug report with Hystrix: Netflix/Hystrix#257It appeared starting with v0.17 and still exists in the master branch.
I have tracked it down to this code in ReplaySubject.java:
A terminal value is being emitted before the
onNext
is received, yet in the Hystrix case it is emitting a value. I'm working on a stand-alone test case for ReplaySubject.The text was updated successfully, but these errors were encountered: