-
Notifications
You must be signed in to change notification settings - Fork 247
Description
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:
- Optimize tests aio-libs/aiohttp#3419
- pytest-aiohttp + pytest-xdist cause RuntimeError: set_wakeup_fd only works in main thread aio-libs/aiohttp#3450
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 / python/cpython#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:
pytest-xdist/src/xdist/workermanage.py
Line 41 in c5fadcd
| self.group = execnet.Group() |
@nicoddemus do you have any insight into this? I'm rather lost at this point. Is there any way to avoid this race condition?