-
-
Notifications
You must be signed in to change notification settings - Fork 339
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
Should run_sync_in_worker_thread count as a blocked task for wait_all_tasks_blocked / autojump_clock? #456
Comments
Including the minimal example from the discussion. The example employs pytest-trio to run this test function with a @pytest.mark.trio
async def test_worker_thread_autojump(nursery, autojump_clock):
def slowish_task():
for i in range(1000000):
pass
return 'foo'
async def async_run_task(queue):
result = await trio.run_sync_in_worker_thread(slowish_task)
await queue.put(result)
queue = trio.Queue(1)
nursery.start_soon(async_run_task, queue)
with trio.fail_after(300):
assert await queue.get() == 'foo' This test might fail with a Tricky part: the code I was exercising through this test didn't make it immediately obvious that it was spawning a worker thread. My expectation was that code that doesn't depend on I/O would interact well with @njsmith mentioned that implicitly waiting for a worker thread happens in Trio itself (in Should Pros:
Cons:
The last question (*) makes me wonder whether this issue might indicate that there are different semantics in the general context of "running a function synchronously in a worker thread". Maybe it's up to the implementation to specify that we are spawning a thread with the expectation that its running state is bound to the task that is waiting for it (i.e. it should be opaque to users that we are in fact spawning a thread to do our job). Simpler alternatives: add a note to the documentation for autojump; add a |
If we do do something like this, then I think it'll be by exposing some function in hazmat that lets you declare that a task should be considered "not blocked" even if it looks like it is (and also a way to set it back afterwards of course). Then Ideally, worker threads should only be used for blocking (io bound) code. If you try to use them for CPU bound code, then you run into bugs in CPython's GIL, where it ends up starving one of the threads. So maybe the On the other hand, when using autojump_clock, there's something weird about the idea that part of your program just jumped forward in time, but the getaddrinfo didn't get the memo and is still running. It is a general limitation of autojump_clock that it only works on stuff actually running inside trio; it can't control threads, or that memcached server you spun up to run your tests against, etc. And when trio is running something in a worker thread, it means trio knows that it can't pull its magic trick and make it seamless, so maybe it shouldn't try. Hmm hmm, this is tricky! We should definitely add a note to the docs in any case :-) |
Additional wrinkle – the idea here: python-trio/pytest-trio#53 (comment) – depends on the current behavior where worker threads don't count as running for |
#1085 suggests another possibility, that Trio keep track of whether it expects any Maybe the Relevant golang bug: golang/go#21576 |
If we did use a thread to implement timeouts in pytest-trio, then it's also an interesting case, because it should not count as an I/O source for the deadlock detector. Note that there are potentially other ways to implement this too though. OK let's work through some intuitions:
|
See some discussion here: https://gitter.im/python-trio/general?at=5a8f0962c3c5f8b90df08c95
CC: @sorcio
The text was updated successfully, but these errors were encountered: