ReactiveX / RxPY

ReactiveX for Python
https://rxpy.rtfd.io
MIT License
4.81k stars 361 forks source link

Possible race condition with ReplaySubject #191

Closed frederikaalund closed 6 years ago

frederikaalund commented 7 years ago

I'm using an unbounded ReplaySubject

self.detect_results = ReplaySubject(scheduler=scheduler)

where scheduler is the AsyncIOScheduler.

When I push values to self.detect_results

 self.detect_results.on_next(detect_result)

I sometimes get an exception (see log output below). This exception occurs very rarely (approximately once for every 100000 on_next calls).

Everything is running on the same thread. I'm using AsyncIO for all scheduling; making sure to pass along the scheduler for all scheduler-enabled RxPy operators.

I'm using RxPy v1.5.9.

Raw log:

Jul 20 09:07:19 bactobox-2 sensord: [sensord.measurement Could not combine result
Jul 20 09:07:20 bactobox-2 sensord: [sensord.measurement Reason:
Jul 20 09:07:20 bactobox-2 sensord: Traceback (most recent call last):
Jul 20 09:07:20 bactobox-2 sensord:   File "/opt/lib/python3.6/site-packages/sensord/measurement/measurement.py", line 109, in combine_result
Jul 20 09:07:20 bactobox-2 sensord:     self.detect_results.on_next(detect_result)
Jul 20 09:07:20 bactobox-2 sensord:   File "usr/lib/python3.6/site-packages/rx/subjects/replaysubject.py", line 99, in on_next
Jul 20 09:07:20 bactobox-2 sensord:   File "usr/lib/python3.6/site-packages/rx/core/scheduledobserver.py", line 47, in ensure_active
Jul 20 09:07:20 bactobox-2 sensord:   File "usr/lib/python3.6/site-packages/rx/disposables/serialdisposable.py", line 34, in set_disposable
Jul 20 09:07:20 bactobox-2 sensord:   File "usr/lib/python3.6/site-packages/rx/disposables/compositedisposable.py", line 66, in dispose
Jul 20 09:07:20 bactobox-2 sensord:   File "usr/lib/python3.6/site-packages/rx/disposables/singleassignmentdisposable.py", line 55, in dispose
Jul 20 09:07:20 bactobox-2 sensord:   File "usr/lib/python3.6/site-packages/rx/disposables/compositedisposable.py", line 66, in dispose
Jul 20 09:07:20 bactobox-2 sensord:   File "usr/lib/python3.6/site-packages/rx/disposables/singleassignmentdisposable.py", line 55, in dispose
Jul 20 09:07:20 bactobox-2 sensord:   File "usr/lib/python3.6/site-packages/rx/disposables/compositedisposable.py", line 66, in dispose
Jul 20 09:07:20 bactobox-2 sensord:   File "usr/lib/python3.6/site-packages/rx/disposables/singleassignmentdisposable.py", line 55, in dispose
Jul 20 09:07:20 bactobox-2 sensord:   File "usr/lib/python3.6/site-packages/rx/disposables/compositedisposable.py", line 66, in dispose
Jul 20 09:07:20 bactobox-2 sensord:   File "usr/lib/python3.6/site-packages/rx/disposables/singleassignmentdisposable.py", line 55, in dispose
Jul 20 09:07:20 bactobox-2 sensord:   File "usr/lib/python3.6/site-packages/rx/disposables/compositedisposable.py", line 66, in dispose
Jul 20 09:07:20 bactobox-2 sensord:   File "usr/lib/python3.6/site-packages/rx/disposables/singleassignmentdisposable.py", line 55, in dispose
Jul 20 09:07:20 bactobox-2 sensord:   File "usr/lib/python3.6/site-packages/rx/disposables/compositedisposable.py", line 66, in dispose
Jul 20 09:07:20 bactobox-2 sensord:   File "usr/lib/python3.6/site-packages/rx/disposables/singleassignmentdisposable.py", line 55, in dispose
Jul 20 09:07:20 bactobox-2 sensord:   File "usr/lib/python3.6/site-packages/rx/disposables/compositedisposable.py", line 66, in dispose
Jul 20 09:07:20 bactobox-2 sensord:   File "usr/lib/python3.6/site-packages/rx/disposables/singleassignmentdisposable.py", line 55, in dispose
Jul 20 09:07:20 bactobox-2 sensord:   File "usr/lib/python3.6/site-packages/rx/disposables/compositedisposable.py", line 66, in dispose
Jul 20 09:07:20 bactobox-2 sensord:   File "usr/lib/python3.6/site-packages/rx/disposables/singleassignmentdisposable.py", line 55, in dispose
Jul 20 09:07:20 bactobox-2 sensord:   File "usr/lib/python3.6/site-packages/rx/disposables/compositedisposable.py", line 66, in dispose
Jul 20 09:07:20 bactobox-2 sensord:   File "usr/lib/python3.6/site-packages/rx/disposables/singleassignmentdisposable.py", line 55, in dispose
Jul 20 09:07:20 bactobox-2 sensord:   File "usr/lib/python3.6/site-packages/rx/disposables/compositedisposable.py", line 66, in dispose
Jul 20 09:07:20 bactobox-2 sensord:   File "usr/lib/python3.6/site-packages/rx/disposables/singleassignmentdisposable.py", line 55, in dispose
Jul 20 09:07:20 bactobox-2 sensord:   File "usr/lib/python3.6/site-packages/rx/disposables/compositedisposable.py", line 66, in dispose
Jul 20 09:07:20 bactobox-2 sensord:   File "usr/lib/python3.6/site-packages/rx/disposables/singleassignmentdisposable.py", line 55, in dispose
Jul 20 09:07:20 bactobox-2 sensord:   File "usr/lib/python3.6/site-packages/rx/disposables/compositedisposable.py", line 66, in dispose
Jul 20 09:07:20 bactobox-2 sensord:   File "usr/lib/python3.6/site-packages/rx/disposables/singleassignmentdisposable.py", line 55, in dispose
Jul 20 09:07:20 bactobox-2 sensord:   File "usr/lib/python3.6/site-packages/rx/disposables/compositedisposable.py", line 66, in dispose
Jul 20 09:07:20 bactobox-2 sensord:   File "usr/lib/python3.6/site-packages/rx/disposables/singleassignmentdisposable.py", line 55, in dispose
Jul 20 09:07:20 bactobox-2 sensord:   File "usr/lib/python3.6/site-packages/rx/disposables/compositedisposable.py", line 66, in dispose
Jul 20 09:07:20 bactobox-2 sensord:   File "usr/lib/python3.6/site-packages/rx/disposables/singleassignmentdisposable.py", line 55, in dispose
Jul 20 09:07:20 bactobox-2 sensord:   File "usr/lib/python3.6/site-packages/rx/disposables/compositedisposable.py", line 66, in dispose
Jul 20 09:07:20 bactobox-2 sensord:   File "usr/lib/python3.6/site-packages/rx/disposables/singleassignmentdisposable.py", line 55, in dispose
Jul 20 09:07:20 bactobox-2 sensord:   File "usr/lib/python3.6/site-packages/rx/disposables/compositedisposable.py", line 66, in dispose
Jul 20 09:07:20 bactobox-2 sensord:   File "usr/lib/python3.6/site-packages/rx/disposables/singleassignmentdisposable.py", line 55, in dispose
Jul 20 09:07:20 bactobox-2 sensord:   File "usr/lib/python3.6/site-packages/rx/disposables/compositedisposable.py", line 66, in dispose
Jul 20 09:07:20 bactobox-2 sensord:   File "usr/lib/python3.6/site-packages/rx/disposables/singleassignmentdisposable.py", line 55, in dispose
Jul 20 09:07:20 bactobox-2 sensord:   File "usr/lib/python3.6/site-packages/rx/disposables/compositedisposable.py", line 66, in dispose
Jul 20 09:07:20 bactobox-2 sensord:   File "usr/lib/python3.6/site-packages/rx/disposables/singleassignmentdisposable.py", line 55, in dispose
Jul 20 09:07:20 bactobox-2 sensord:   File "usr/lib/python3.6/site-packages/rx/disposables/compositedisposable.py", line 66, in dispose
Jul 20 09:07:20 bactobox-2 sensord:   File "usr/lib/python3.6/site-packages/rx/disposables/singleassignmentdisposable.py", line 55, in dispose
Jul 20 09:07:20 bactobox-2 sensord:   File "usr/lib/python3.6/site-packages/rx/disposables/compositedisposable.py", line 66, in dispose
Jul 20 09:07:20 bactobox-2 sensord:   File "usr/lib/python3.6/site-packages/rx/disposables/singleassignmentdisposable.py", line 55, in dispose
Jul 20 09:07:20 bactobox-2 sensord:   File "usr/lib/python3.6/site-packages/rx/disposables/compositedisposable.py", line 66, in dispose
Jul 20 09:07:20 bactobox-2 sensord:   File "usr/lib/python3.6/site-packages/rx/disposables/singleassignmentdisposable.py", line 55, in dispose
Jul 20 09:07:20 bactobox-2 sensord:   File "usr/lib/python3.6/site-packages/rx/disposables/compositedisposable.py", line 66, in dispose
Jul 20 09:07:20 bactobox-2 sensord:   File "usr/lib/python3.6/site-packages/rx/disposables/singleassignmentdisposable.py", line 55, in dispose
Jul 20 09:07:20 bactobox-2 sensord:   File "usr/lib/python3.6/site-packages/rx/disposables/compositedisposable.py", line 66, in dispose
Jul 20 09:07:20 bactobox-2 sensord:   File "usr/lib/python3.6/site-packages/rx/disposables/singleassignmentdisposable.py", line 55, in dispose
Jul 20 09:07:20 bactobox-2 sensord:   File "usr/lib/python3.6/site-packages/rx/disposables/compositedisposable.py", line 66, in dispose
Jul 20 09:07:20 bactobox-2 sensord:   File "usr/lib/python3.6/site-packages/rx/disposables/singleassignmentdisposable.py", line 55, in dispose
Jul 20 09:07:20 bactobox-2 sensord:   File "usr/lib/python3.6/site-packages/rx/disposables/compositedisposable.py", line 66, in dispose
Jul 20 09:07:20 bactobox-2 sensord:   File "usr/lib/python3.6/site-packages/rx/disposables/singleassignmentdisposable.py", line 55, in dispose
Jul 20 09:07:20 bactobox-2 sensord:   File "usr/lib/python3.6/site-packages/rx/disposables/compositedisposable.py", line 66, in dispose
Jul 20 09:07:20 bactobox-2 sensord:   File "usr/lib/python3.6/site-packages/rx/disposables/singleassignmentdisposable.py", line 55, in dispose
Jul 20 09:07:20 bactobox-2 sensord:   File "usr/lib/python3.6/site-packages/rx/disposables/compositedisposable.py", line 66, in dispose
Jul 20 09:07:20 bactobox-2 sensord:   File "usr/lib/python3.6/site-packages/rx/disposables/singleassignmentdisposable.py", line 55, in dispose
Jul 20 09:07:20 bactobox-2 sensord:   File "usr/lib/python3.6/site-packages/rx/disposables/compositedisposable.py", line 66, in dispose
Jul 20 09:07:20 bactobox-2 sensord:   File "usr/lib/python3.6/site-packages/rx/disposables/singleassignmentdisposable.py", line 55, in dispose
Jul 20 09:07:20 bactobox-2 sensord:   File "usr/lib/python3.6/site-packages/rx/disposables/compositedisposable.py", line 66, in dispose
Jul 20 09:07:20 bactobox-2 sensord:   File "usr/lib/python3.6/site-packages/rx/disposables/singleassignmentdisposable.py", line 55, in dispose
Jul 20 09:07:20 bactobox-2 sensord:   File "usr/lib/python3.6/site-packages/rx/disposables/compositedisposable.py", line 66, in dispose
Jul 20 09:07:20 bactobox-2 sensord:   File "usr/lib/python3.6/site-packages/rx/disposables/singleassignmentdisposable.py", line 55, in dispose
Jul 20 09:07:20 bactobox-2 sensord:   File "usr/lib/python3.6/site-packages/rx/disposables/compositedisposable.py", line 66, in dispose
Jul 20 09:07:20 bactobox-2 sensord:   File "usr/lib/python3.6/site-packages/rx/disposables/singleassignmentdisposable.py", line 55, in dispose
Jul 20 09:07:20 bactobox-2 sensord:   File "usr/lib/python3.6/site-packages/rx/disposables/compositedisposable.py", line 66, in dispose
Jul 20 09:07:20 bactobox-2 sensord:   File "usr/lib/python3.6/site-packages/rx/disposables/singleassignmentdisposable.py", line 55, in dispose
Jul 20 09:07:20 bactobox-2 sensord:   File "usr/lib/python3.6/site-packages/rx/disposables/compositedisposable.py", line 66, in dispose
Jul 20 09:07:20 bactobox-2 sensord:   File "usr/lib/python3.6/site-packages/rx/disposables/singleassignmentdisposable.py", line 55, in dispose
Jul 20 09:07:20 bactobox-2 sensord:   File "usr/lib/python3.6/site-packages/rx/disposables/compositedisposable.py", line 66, in dispose
Jul 20 09:07:20 bactobox-2 sensord:   File "usr/lib/python3.6/site-packages/rx/disposables/singleassignmentdisposable.py", line 55, in dispose
Jul 20 09:07:20 bactobox-2 sensord:   File "usr/lib/python3.6/site-packages/rx/disposables/compositedisposable.py", line 66, in dispose
Jul 20 09:07:20 bactobox-2 sensord:   File "usr/lib/python3.6/site-packages/rx/disposables/singleassignmentdisposable.py", line 55, in dispose
Jul 20 09:07:20 bactobox-2 sensord:   File "usr/lib/python3.6/site-packages/rx/disposables/compositedisposable.py", line 66, in dispose
Jul 20 09:07:20 bactobox-2 sensord:   File "usr/lib/python3.6/site-packages/rx/disposables/singleassignmentdisposable.py", line 55, in dispose
Jul 20 09:07:20 bactobox-2 sensord:   File "usr/lib/python3.6/site-packages/rx/disposables/compositedisposable.py", line 66, in 

Looks like inifinite recursion in the dispose method. Could two disposables be trying to dispose each other in a cycle?

dbrattli commented 7 years ago

Thanks, I will look into this.

MichaelSchneeberger commented 7 years ago

That looks very similar to #184

diorcety commented 6 years ago

Really easy to reproduce:

import rx

obs = rx.Observable.range(0, 20000)
# obs = obs.replay(None, 1).ref_count()  # Uncomment for triggering RuntimeError: maximum recursion depth exceeded

a = list(obs.last().to_blocking())[0]
print(a)
diorcety commented 6 years ago

The issue is between ReplaySubject, ScheduledObserver and CurrentThreadScheduler

diorcety commented 6 years ago

In the example if you change the replay's scheduler by immediate scheduler, it works

dbrattli commented 6 years ago

I've pushed a new version (1.6.1) of Rx. Please check if it fixes this issue.

frederikaalund commented 6 years ago

@diorcety Great work hunting down this bug and making it reproducible. Cheers! Using your code sample, the bug does indeed seem to be solved.

I've pushed a new version (1.6.1) of Rx. Please check if it fixes this issue.

Thanks for that. I'm really glad to see that issue resolved. I've updated our build system to track 44081a1bba8e897768a22da2ae0580456ff13285 (should be 1.6.1; I couldn't find a tag for this release). We will be using this version going forward. I'll reopen the issue if the error reappears (though I'm feeling confident that it should be solved now).

diorcety commented 6 years ago

Indeed the 1.6.1 version fixes the issue

lock[bot] commented 5 years ago

This thread has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.