pytest-parallel icon indicating copy to clipboard operation
pytest-parallel copied to clipboard

Pytest-parallel and pytest-timeout hang when used together

Open etragas-fathom opened this issue 5 years ago • 3 comments

This isn't a bug of pytest-parallel, but I wanted to raise it as a noteworthy issue and leave up to you to decide if it's worth working around pytest-timeout somehow.

Background: https://pypi.org/project/pytest-timeout/ (Potentially) Relevant issue for python-xdist: https://bitbucket.org/pytest-dev/pytest-timeout/issues/8/pytest-xdist-interop-signal-only-works-in

If you have any questions I'll be happy to answer.

Summary: Setup:

pip install pytest-parallel==0.0.8
pip install pytest-timeout==1.3.2

Config (filename: pytest.ini):

[pytest]
filterwarnings =
    ignore:::tensorflow
timeout = 1
addopts = --workers auto

Test File(filename: fail.py):

def test_fail():
    assert False

def test_fail_2():
    assert False

Command:

Eliass-MacBook-Pro:diseaseTools etragas$ py_test fail.py

Output:

================================================================================== test session starts ==================================================================================
platform linux -- Python 3.6.7, pytest-3.8.0, py-1.7.0, pluggy-0.8.0
rootdir: /usr/src/app, inifile: pytest.ini
plugins: snapshottest-0.5.0, timeout-1.3.2, parallel-0.0.8, mock-1.5.0, cov-2.5.1, celery-4.2.1
timeout: 1.0s
timeout method: signal
timeout func_only: False
collected 2 items
pytest-parallel: 6 workers (processes), 1 test per worker (thread)
Exception in thread Thread-1:
Traceback (most recent call last):
  File "/usr/local/lib/python3.6/threading.py", line 916, in _bootstrap_inner
    self.run()
  File "/usr/local/lib/python3.6/site-packages/pytest_parallel/__init__.py", line 80, in run
    run_test(self.session, item, None)
  File "/usr/local/lib/python3.6/site-packages/pytest_parallel/__init__.py", line 50, in run_test
    item.ihook.pytest_runtest_protocol(item=item, nextitem=nextitem)
  File "/usr/local/lib/python3.6/site-packages/pluggy/hooks.py", line 284, in __call__
    return self._hookexec(self, self.get_hookimpls(), kwargs)
  File "/usr/local/lib/python3.6/site-packages/pluggy/manager.py", line 67, in _hookexec
    return self._inner_hookexec(hook, methods, kwargs)
  File "/usr/local/lib/python3.6/site-packages/pluggy/manager.py", line 61, in <lambda>
    firstresult=hook.spec.opts.get("firstresult") if hook.spec else False,
  File "/usr/local/lib/python3.6/site-packages/pluggy/callers.py", line 208, in _multicall
    return outcome.get_result()
  File "/usr/local/lib/python3.6/site-packages/pluggy/callers.py", line 80, in get_result
    raise ex[1].with_traceback(ex[2])
  File "/usr/local/lib/python3.6/site-packages/pluggy/callers.py", line 182, in _multicall
    next(gen)  # first yield
  File "/usr/local/lib/python3.6/site-packages/pytest_timeout.py", line 91, in pytest_runtest_protocol
    timeout_setup(item)
  File "/usr/local/lib/python3.6/site-packages/pytest_timeout.py", line 144, in timeout_setup
    signal.signal(signal.SIGALRM, handler)
  File "/usr/local/lib/python3.6/signal.py", line 47, in signal
    handler = _signal.signal(_enum_to_int(signalnum), _enum_to_int(handler))
ValueError: signal only works in main thread

Exception in thread Thread-1:
Traceback (most recent call last):
  File "/usr/local/lib/python3.6/threading.py", line 916, in _bootstrap_inner
    self.run()
  File "/usr/local/lib/python3.6/site-packages/pytest_parallel/__init__.py", line 80, in run
    run_test(self.session, item, None)
  File "/usr/local/lib/python3.6/site-packages/pytest_parallel/__init__.py", line 50, in run_test
    item.ihook.pytest_runtest_protocol(item=item, nextitem=nextitem)
  File "/usr/local/lib/python3.6/site-packages/pluggy/hooks.py", line 284, in __call__
    return self._hookexec(self, self.get_hookimpls(), kwargs)
  File "/usr/local/lib/python3.6/site-packages/pluggy/manager.py", line 67, in _hookexec
    return self._inner_hookexec(hook, methods, kwargs)
  File "/usr/local/lib/python3.6/site-packages/pluggy/manager.py", line 61, in <lambda>
    firstresult=hook.spec.opts.get("firstresult") if hook.spec else False,
  File "/usr/local/lib/python3.6/site-packages/pluggy/callers.py", line 208, in _multicall
    return outcome.get_result()
  File "/usr/local/lib/python3.6/site-packages/pluggy/callers.py", line 80, in get_result
    raise ex[1].with_traceback(ex[2])
  File "/usr/local/lib/python3.6/site-packages/pluggy/callers.py", line 182, in _multicall
    next(gen)  # first yield
  File "/usr/local/lib/python3.6/site-packages/pytest_timeout.py", line 91, in pytest_runtest_protocol
    timeout_setup(item)
  File "/usr/local/lib/python3.6/site-packages/pytest_timeout.py", line 144, in timeout_setup
    signal.signal(signal.SIGALRM, handler)
  File "/usr/local/lib/python3.6/signal.py", line 47, in signal
    handler = _signal.signal(_enum_to_int(signalnum), _enum_to_int(handler))
ValueError: signal only works in main thread

etragas-fathom avatar Nov 16 '18 01:11 etragas-fathom

Thanks for filing. The fix probably requires monkeypatching os._exit

kevlened avatar Nov 16 '18 02:11 kevlened

Is there a plan to fix this issue?

ninoseki avatar Jul 23 '20 11:07 ninoseki

Not sure if this has already been addressed or not. But I was able to fix the problem with this decorator: @pytest.mark.timeout(timeout=60, method='thread')

kathrynline avatar Dec 15 '20 00:12 kathrynline