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
[email protected]
https://mail.python.org/mailman/listinfo/pytest-commit