New issue 625: xdist: deadlock under pypy https://bitbucket.org/hpk42/pytest/issue/625/xdist-deadlock-under-pypy
Buck Evan: Below is a minimal reproduction. It seems that a few factors need to conspire to tickle this bug: 1. test uses subprocess.Popen and tmpdir fixture 2. test is not run first 3. runner is passed -n greater than 2 (although exactly 2 makes it most likely) Reproduction script: ``` #!python # This is my commandline, on osx: # $ py.test -vvs -n 2 ./demo.py # # I haven't been able to test linux-pypy, but I can't repro under osx-cpython. # # I also notice that each deadlock leaks a worker process from xdist. # I have to go clean them up with killall def test_dummy(tmpdir): """deadlock doesn't occur if i remove this test, or if i put it second""" return import pytest @pytest.mark.timeout(10) # this is necessary just to get some feedback from the test, the deadlock still happens without it. def test_deadlocks_sometimes(tmpdir): # I haven't seen a deadlock if i remove this fixture. """This deadlocks most often (around 50%) with -n2, but still deadlocks with -n >2. I haven't seen it deadlock with -n1. """ from subprocess import Popen Popen( ('echo', 'hi', 'there!'), # doesn't matter what the command is. close_fds=True, # with True, we get a timeout and two stack traces # with False, I see a FAIL after ten seconds, but it continues to deadlock, # and I get a single, different traceback on ctrl+c ) ``` Traceback with close_fds=True: ``` ____________________________________________________________ test_uncolored_pipe ____________________________________________________________ [gw0] darwin -- Python 3.2.5 /Users/buck/venv/venv-update4/bin/pypy3 tmpdir = local('/private/var/folders/ss/ykf37pld1hl480qcdknf_zc577t9rc/T/pytest-239/popen-gw0/test_uncolored_pipe0') @pytest.mark.timeout(10) def test_uncolored_pipe(tmpdir): tmpdir.chdir() from subprocess import Popen return Popen( ('echo', 'hi', 'there!'), > close_fds=True, ).wait() /Users/buck/trees/yelp/venv-update/color.py:13: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /Users/buck/prefices/brew/Cellar/pypy3/2.3.1_1/libexec/lib-python/3/subprocess.py:744: in __init__ restore_signals, start_new_session) /Users/buck/prefices/brew/Cellar/pypy3/2.3.1_1/libexec/lib-python/3/subprocess.py:1359: in _execute_child part = _eintr_retry_call(os.read, errpipe_read, 50000) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ func = <built-in function read>, args = (10, 50000) def _eintr_retry_call(func, *args): while True: try: > return func(*args) E Failed: Timeout >10s /Users/buck/prefices/brew/Cellar/pypy3/2.3.1_1/libexec/lib-python/3/subprocess.py:455: Failed ----------------------------------------------------------- Captured stderr call ------------------------------------------------------------ ~~~~~~~~~~~~~~~~~~~~~~~ Stack of <unknown> (4433383424) ~~~~~~~~~~~~~~~~~~~~~~~~ File "/Users/buck/venv/venv-update4/site-packages/execnet/gateway_base.py", line 254, in _perform_spawn reply.run() File "/Users/buck/venv/venv-update4/site-packages/execnet/gateway_base.py", line 192, in run self._result = func(*args, **kwargs) File "/Users/buck/venv/venv-update4/site-packages/execnet/gateway_base.py", line 914, in _thread_receiver msg = Message.from_io(io) File "/Users/buck/venv/venv-update4/site-packages/execnet/gateway_base.py", line 390, in from_io header = io.read(9) # type 1, channel 4, payload 4 File "/Users/buck/venv/venv-update4/site-packages/execnet/gateway_base.py", line 360, in read data = self._read(numbytes-len(buf)) ========================================================== short test summary info ========================================================== FAIL color.py::test_uncolored_pipe ==================================================== 1 failed, 1 passed in 11.21 seconds ==================================================== ``` Traceback with close_fds=False: ``` color.py::test_deadlocks_sometimes [gw1] FAILED color.py::test_deadlocks_sometimes ^CTraceback (most recent call last): File "/Users/buck/venv/venv-update4/bin/py.test", line 9, in <module> load_entry_point('pytest==2.6.4', 'console_scripts', 'py.test')() File "/Users/buck/venv/venv-update4/site-packages/_pytest/config.py", line 41, in main return config.hook.pytest_cmdline_main(config=config) File "/Users/buck/venv/venv-update4/site-packages/_pytest/core.py", line 413, in __call__ return self._docall(methods, kwargs) File "/Users/buck/venv/venv-update4/site-packages/_pytest/core.py", line 424, in _docall res = mc.execute() File "/Users/buck/venv/venv-update4/site-packages/_pytest/core.py", line 315, in execute res = method(**kwargs) File "/Users/buck/venv/venv-update4/site-packages/_pytest/main.py", line 116, in pytest_cmdline_main return wrap_session(config, _main) File "/Users/buck/venv/venv-update4/site-packages/_pytest/main.py", line 109, in wrap_session exitstatus=session.exitstatus) File "/Users/buck/venv/venv-update4/site-packages/_pytest/core.py", line 413, in __call__ return self._docall(methods, kwargs) File "/Users/buck/venv/venv-update4/site-packages/_pytest/core.py", line 424, in _docall res = mc.execute() File "/Users/buck/venv/venv-update4/site-packages/_pytest/core.py", line 315, in execute res = method(**kwargs) File "/Users/buck/venv/venv-update4/site-packages/xdist/dsession.py", line 487, in pytest_sessionfinish nm.teardown_nodes() File "/Users/buck/venv/venv-update4/site-packages/xdist/slavemanage.py", line 59, in teardown_nodes self.group.terminate(self.EXIT_TIMEOUT) File "/Users/buck/venv/venv-update4/site-packages/execnet/multi.py", line 204, in terminate for gw in self._gateways_to_join]) File "/Users/buck/venv/venv-update4/site-packages/execnet/multi.py", line 293, in safe_terminate workerpool.waitall() File "/Users/buck/venv/venv-update4/site-packages/execnet/gateway_base.py", line 302, in waitall return my_waitall_event.wait(timeout=timeout) File "/Users/buck/prefices/brew/Cellar/pypy3/2.3.1_1/libexec/lib-python/3/threading.py", line 422, in wait signaled = self._cond.wait(timeout) File "/Users/buck/prefices/brew/Cellar/pypy3/2.3.1_1/libexec/lib-python/3/threading.py", line 235, in wait waiter.acquire() KeyboardInterrupt ``` _______________________________________________ pytest-commit mailing list pytest-commit@python.org https://mail.python.org/mailman/listinfo/pytest-commit