Skip to content

AttributeError: 'Config' object has no attribute 'fault_handler_stderr' when enabling faulthandler via Python #6575

@The-Compiler

Description

@The-Compiler

When launching pytest 5.3.2 with python3 -X faulthandler -m pytest (or PYTHONFAULTHANDLER=1, or enabling Development Mode) and with a faulthandler_timeout set, pytest fails with this after collecting:

INTERNALERROR> Traceback (most recent call last):
INTERNALERROR>   File "/home/florian/proj/qutebrowser/git/.tox/py37-pyqt513/lib/python3.7/site-packages/_pytest/main.py", line 196, in wrap_session
INTERNALERROR>     session.exitstatus = doit(config, session) or 0
INTERNALERROR>   File "/home/florian/proj/qutebrowser/git/.tox/py37-pyqt513/lib/python3.7/site-packages/_pytest/main.py", line 246, in _main
INTERNALERROR>     config.hook.pytest_runtestloop(session=session)
INTERNALERROR>   File "/home/florian/proj/qutebrowser/git/.tox/py37-pyqt513/lib/python3.7/site-packages/pluggy/hooks.py", line 286, in __call__
INTERNALERROR>     return self._hookexec(self, self.get_hookimpls(), kwargs)
INTERNALERROR>   File "/home/florian/proj/qutebrowser/git/.tox/py37-pyqt513/lib/python3.7/site-packages/pluggy/manager.py", line 93, in _hookexec
INTERNALERROR>     return self._inner_hookexec(hook, methods, kwargs)
INTERNALERROR>   File "/home/florian/proj/qutebrowser/git/.tox/py37-pyqt513/lib/python3.7/site-packages/pluggy/manager.py", line 87, in <lambda>
INTERNALERROR>     firstresult=hook.spec.opts.get("firstresult") if hook.spec else False,
INTERNALERROR>   File "/home/florian/proj/qutebrowser/git/.tox/py37-pyqt513/lib/python3.7/site-packages/pluggy/callers.py", line 208, in _multicall
INTERNALERROR>     return outcome.get_result()
INTERNALERROR>   File "/home/florian/proj/qutebrowser/git/.tox/py37-pyqt513/lib/python3.7/site-packages/pluggy/callers.py", line 80, in get_result
INTERNALERROR>     raise ex[1].with_traceback(ex[2])
INTERNALERROR>   File "/home/florian/proj/qutebrowser/git/.tox/py37-pyqt513/lib/python3.7/site-packages/pluggy/callers.py", line 187, in _multicall
INTERNALERROR>     res = hook_impl.function(*args)
INTERNALERROR>   File "/home/florian/proj/qutebrowser/git/.tox/py37-pyqt513/lib/python3.7/site-packages/_pytest/main.py", line 270, in pytest_runtestloop
INTERNALERROR>     item.config.hook.pytest_runtest_protocol(item=item, nextitem=nextitem)
INTERNALERROR>   File "/home/florian/proj/qutebrowser/git/.tox/py37-pyqt513/lib/python3.7/site-packages/pluggy/hooks.py", line 286, in __call__
INTERNALERROR>     return self._hookexec(self, self.get_hookimpls(), kwargs)
INTERNALERROR>   File "/home/florian/proj/qutebrowser/git/.tox/py37-pyqt513/lib/python3.7/site-packages/pluggy/manager.py", line 93, in _hookexec
INTERNALERROR>     return self._inner_hookexec(hook, methods, kwargs)
INTERNALERROR>   File "/home/florian/proj/qutebrowser/git/.tox/py37-pyqt513/lib/python3.7/site-packages/pluggy/manager.py", line 87, in <lambda>
INTERNALERROR>     firstresult=hook.spec.opts.get("firstresult") if hook.spec else False,
INTERNALERROR>   File "/home/florian/proj/qutebrowser/git/.tox/py37-pyqt513/lib/python3.7/site-packages/pluggy/callers.py", line 208, in _multicall
INTERNALERROR>     return outcome.get_result()
INTERNALERROR>   File "/home/florian/proj/qutebrowser/git/.tox/py37-pyqt513/lib/python3.7/site-packages/pluggy/callers.py", line 80, in get_result
INTERNALERROR>     raise ex[1].with_traceback(ex[2])
INTERNALERROR>   File "/home/florian/proj/qutebrowser/git/.tox/py37-pyqt513/lib/python3.7/site-packages/pluggy/callers.py", line 182, in _multicall
INTERNALERROR>     next(gen)  # first yield
INTERNALERROR>   File "/home/florian/proj/qutebrowser/git/.tox/py37-pyqt513/lib/python3.7/site-packages/_pytest/faulthandler.py", line 60, in pytest_runtest_protocol
INTERNALERROR>     stderr = item.config.fault_handler_stderr
INTERNALERROR> AttributeError: 'Config' object has no attribute 'fault_handler_stderr'

As a workaround, -p no:faulthandler can be used.

It looks like pytest_configure in faulthandler.py exits early if it's already enabled:

def pytest_configure(config):
import faulthandler
# avoid trying to dup sys.stderr if faulthandler is already enabled
if faulthandler.is_enabled():
return
stderr_fd_copy = os.dup(_get_stderr_fileno())
config.fault_handler_stderr = os.fdopen(stderr_fd_copy, "w")
faulthandler.enable(file=config.fault_handler_stderr)

Thus it doesn't set the config.fault_handler_stderr attribute, but later pytest_runtest_protocol assumes that it exists:

@pytest.hookimpl(hookwrapper=True)
def pytest_runtest_protocol(item):
timeout = float(item.config.getini("faulthandler_timeout") or 0.0)
if timeout > 0:
import faulthandler
stderr = item.config.fault_handler_stderr

Metadata

Metadata

Assignees

No one assigned

    Labels

    type: bugproblem that needs to be addressed

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions