pytest-xdist: `pytest-xdist` breaks asyncio-based code expecting to be run in the main thread
When asyncio
-based software needs to register signal
handlers, calling add_signal_handler()
only works when the current thread is main and raises a RuntimeError
otherwise.
When I first tried integrating pytest-xdist
into aiohttp
’s test suite a few years ago, we’ve faced a problem that about 15% of pytest invocations would hit this and had to disable the plugin:
The reproducer is to clone aio-libs/aiohttp, add -n auto
to addopts
somewhere in setup.cfg
, and re-run make test
until you see the traceback. On aiohttp side, it’s coming from the watcher.attach_loop()
call invoked from the pytest plugin @ https://github.com/aio-libs/aiohttp/blob/742a8b6/aiohttp/pytest_plugin.py#L161.
Now that I’ve had some time to try to debug what’s happening, I’ve stuck a debugger right before the line that raises RuntimeError
and confirmed that the thread wasn’t main:
>>> import threading
>>> threading.enumerate()
[<_MainThread(MainThread, started 140666216200000)>, <_DummyThread(Dummy-1, started daemon 140666196751936)>]
>>> threading.current_thread()
<_DummyThread(Dummy-1, started daemon
140666196751936)>
@asvetlov It should be possible to fix this on the asyncio
side with ThreadedChildWatcher
(https://bugs.python.org/issue35621 / https://github.com/python/cpython/pull/14344) but it only appeared in the stdlib since Python 3.8: https://stackoverflow.com/a/58614689/595220.
It’s hard to pinpoint where that thread is coming from but it appears to be execnet
’s fault: https://github.com/pytest-dev/pytest-xdist/blob/c5fadcd734b008251fbaa438e0806235d9bd081b/src/xdist/workermanage.py#L41 + https://github.com/pytest-dev/execnet/blob/116637ab183bc078647f281b52e662650e8178e7/execnet/multi.py#L27.
@nicoddemus do you have any insight into this? I’m rather lost at this point. Is there any way to avoid this race condition?
About this issue
- Original URL
- State: open
- Created 3 years ago
- Reactions: 2
- Comments: 36 (29 by maintainers)
Commits related to this issue
- Use ThreadedChildWatcher in tests where available Refs: * https://github.com/pytest-dev/pytest-xdist/issues/620 * https://stackoverflow.com/a/58614689/595220 * https://bugs.python.org/issue3562... — committed to aio-libs/aiohttp by webknjaz 3 years ago
- Use ThreadedChildWatcher in tests where available Refs: * https://github.com/pytest-dev/pytest-xdist/issues/620 * https://stackoverflow.com/a/58614689/595220 * https://bugs.python.org/issue3562... — committed to aio-libs/aiohttp by webknjaz 3 years ago
- Use ThreadedChildWatcher in tests where available Refs: * https://github.com/pytest-dev/pytest-xdist/issues/620 * https://stackoverflow.com/a/58614689/595220 * https://bugs.python.org/issue3562... — committed to aio-libs/aiohttp by webknjaz 3 years ago
- waitclose in _rinfo() call should improve https://github.com/pytest-dev/pytest-xdist/issues/620 — committed to graingert/execnet by graingert 3 years ago
- waitclose in _rinfo() call should improve https://github.com/pytest-dev/pytest-xdist/issues/620 — committed to graingert/execnet by graingert 3 years ago
- Use ThreadedChildWatcher in tests where available Refs: * https://github.com/pytest-dev/pytest-xdist/issues/620 * https://stackoverflow.com/a/58614689/595220 * https://bugs.python.org/issue3562... — committed to aio-libs/aiohttp by webknjaz 3 years ago
- Use ThreadedChildWatcher in tests where available Refs: * https://github.com/pytest-dev/pytest-xdist/issues/620 * https://stackoverflow.com/a/58614689/595220 * https://bugs.python.org/issue3562... — committed to aio-libs/aiohttp by webknjaz 3 years ago
- Speed up unit tests via distributed testing Also use verbose mode on CI since more logs is usually better since getting more is quite literally impossible. The main issue we'll face with this is we'... — committed to ichard26/black by ichard26 3 years ago
- Speed up unit tests via distributed testing Also use verbose mode on CI since more logs is usually better since getting more is quite literally impossible. The main issue we'll face with this is we'... — committed to psf/black by ichard26 3 years ago
- Speed up unit tests via distributed testing Also use verbose mode on CI since more logs is usually better since getting more is quite literally impossible. The main issue we'll face with this is we'... — committed to psf/black by ichard26 3 years ago
- Speed up test suite via distributed testing Since we now run the test suite twice, one with Python 2 and another without, full test runs are getting pretty slow. Let's try to fix that with parallizat... — committed to psf/black by ichard26 3 years ago
- Speed up test suite via distributed testing Since we now run the test suite twice, one with Python 2 and another without, full test runs are getting pretty slow. Let's try to fix that with parallizat... — committed to psf/black by ichard26 3 years ago
- Speed up test suite via distributed testing (#2196) * Speed up test suite via distributed testing Since we now run the test suite twice, one with Python 2 and another without, full test runs are ... — committed to psf/black by ichard26 3 years ago
- Use ThreadedChildWatcher in tests where available Refs: * https://github.com/pytest-dev/pytest-xdist/issues/620 * https://stackoverflow.com/a/58614689/595220 * https://bugs.python.org/issue3562... — committed to sweatybridge/aiohttp by webknjaz 3 years ago
- Use `MultiLoopChildWatcher` in tests where available PR #5862 Refs: * https://github.com/pytest-dev/pytest-xdist/issues/620 * https://stackoverflow.com/a/58614689/595220 * https://bugs.py... — committed to aio-libs/aiohttp by sweatybridge 3 years ago
- Use `MultiLoopChildWatcher` in tests where available PR #5862 Refs: * https://github.com/pytest-dev/pytest-xdist/issues/620 * https://stackoverflow.com/a/58614689/595220 * https://bugs.python.... — committed to aio-libs/aiohttp by sweatybridge 3 years ago
- Use execnet main_thread_only execmodel Use the execnet main_thread_only execmodel so that code which expects to run in the main thread will just work. This execmodel has been proposed in https://git... — committed to zmedico/pytest-xdist by zmedico 5 months ago
- Use execnet main_thread_only execmodel Use the execnet main_thread_only execmodel so that code which expects to run in the main thread will just work. This execmodel has been proposed in https://git... — committed to zmedico/pytest-xdist by zmedico 5 months ago
- Use execnet main_thread_only execmodel Use the execnet main_thread_only execmodel so that code which expects to run in the main thread will just work. This execmodel has been proposed in https://git... — committed to zmedico/pytest-xdist by zmedico 5 months ago
- Use execnet main_thread_only execmodel Use the execnet main_thread_only execmodel so that code which expects to run in the main thread will just work. This execmodel has been merged to the execnet m... — committed to zmedico/pytest-xdist by zmedico 4 months ago
Related to https://github.com/pytest-dev/execnet/issues/96
Ahh that’s a bummer.
In my case we are not really using
asyncio
, but were experiencing the problem of spawning code not in the main thread.Thanks folks for the feedback.
https://github.com/pytest-dev/execnet/blob/master/CHANGELOG.rst#12
1.2 added it
seems like this will be a major pain
@webknjaz I don’t think it’s quite right, because there’s a very small window between when the channel is closed and the primary_thread_task_ready semaphore is set
but it should improve things a lot