-
Notifications
You must be signed in to change notification settings - Fork 550
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
call_soon_threadsafe is not really threadsafe #408
Comments
Can you please help me and review the PR? And if it's possible to release a new version to fix this problem? @fantix @graingert |
Sorry for the late reply and thank you for the careful debugging! The PR removed the start of the idle handler in - if not self.handler_idle.running:
- self.handler_idle.start() That does make sense to me. It would be great if we could have a test to cover the case though. |
Thanks God for you reply me finally! It's do better to have a test case. |
Fixed in uvloop 0.15.3, please feel free to reopen if the issue persists. |
PYTHONASYNCIODEBUG
in env?: yesI have been confused about this bug for about two weeks. In my situation, I create some threads and every thread run a new loop separately. At the same time, I have another thread to invoke
loop.call_soon_threadsafe
to add tasks to loops in other threads. It ran well at first. However loops would close after a-few-hour running and raisedRuntimeError('Event loop stopped before Future completed.')
. Actually some tasks still left in the loop and I haven't closed the loop yet.Because this problem is really hard to reproduce . I took a long time to figure out how it happened and checked if I invoked
loop.close
in somewhere. I added some log atclose
and found the loop stopped suddenly withoutclose
invocation. So I went on and checked libuv docs. There is a suspicious sentenceIf the loop is alive an iteration is started, otherwise the loop will exit immediately. So, when is a loop considered to be alive? If a loop has active and ref’d handles, active requests or closing handles it’s considered to be alive.
. I added some log inuv.uv_run
and it verified that the loop stoped because uv__loop_alive return False!I dove into uvloop and libuv carefully. Disappointedly I found nothing. Code are rigorous and elegant. So I logged around every init and stop when uvloop invoke
uv_handle_t
.Just like thisAfter a few hours execution and 200 thousand lines log file generated, I reproduced the bug again! And the highlight line is where the problem happened.
Because libuv isn't thread safe. The
uv_loop_t.active_handles
will in race condition when we invokecall_soon_threadsafe
in a thread and the loop runs in another thread simultaneously. Actually theloop.handle_async.send
will activate the idle handle in the loop thread. So we don't need to activate the idle handle atcall_soon_threadsafe
Here is my pull request. Approve please😊
The text was updated successfully, but these errors were encountered: