Only re-enable fauthandler during unconfigure if it was enabled before

This commit is contained in:
Bruno Oliveira 2021-01-25 12:28:00 -03:00
parent adc0f29b8f
commit 33861098d9
2 changed files with 33 additions and 13 deletions

View File

@ -12,6 +12,7 @@ from _pytest.store import StoreKey
fault_handler_stderr_key = StoreKey[TextIO]() fault_handler_stderr_key = StoreKey[TextIO]()
fault_handler_originally_enabled_key = StoreKey[bool]()
def pytest_addoption(parser: Parser) -> None: def pytest_addoption(parser: Parser) -> None:
@ -27,6 +28,7 @@ def pytest_configure(config: Config) -> None:
stderr_fd_copy = os.dup(get_stderr_fileno()) stderr_fd_copy = os.dup(get_stderr_fileno())
config._store[fault_handler_stderr_key] = open(stderr_fd_copy, "w") config._store[fault_handler_stderr_key] = open(stderr_fd_copy, "w")
config._store[fault_handler_originally_enabled_key] = faulthandler.is_enabled()
faulthandler.enable(file=config._store[fault_handler_stderr_key]) faulthandler.enable(file=config._store[fault_handler_stderr_key])
@ -38,10 +40,9 @@ def pytest_unconfigure(config: Config) -> None:
if fault_handler_stderr_key in config._store: if fault_handler_stderr_key in config._store:
config._store[fault_handler_stderr_key].close() config._store[fault_handler_stderr_key].close()
del config._store[fault_handler_stderr_key] del config._store[fault_handler_stderr_key]
# Re-enable the faulthandler, attaching it to the default sys.stderr if config._store.get(fault_handler_originally_enabled_key, False):
# so we can see crashes after pytest has finished, usually during # Re-enable the faulthandler if it was originally enabled.
# garbage collection during interpreter shutdown. faulthandler.enable(file=get_stderr_fileno())
faulthandler.enable(file=get_stderr_fileno())
def get_stderr_fileno() -> int: def get_stderr_fileno() -> int:

View File

@ -19,22 +19,41 @@ def test_enabled(pytester: Pytester) -> None:
assert result.ret != 0 assert result.ret != 0
def test_crash_near_exit(pytester: Pytester) -> None: def setup_crashing_test(pytester: Pytester) -> None:
"""Test that fault handler displays crashes that happen even after
pytest is exiting (for example, when the interpreter is shutting down)."""
pytester.makepyfile( pytester.makepyfile(
""" """
import faulthandler import faulthandler
import atexit import atexit
def test_ok(): def test_ok():
atexit.register(faulthandler._sigabrt) atexit.register(faulthandler._sigabrt)
""" """
) )
result = pytester.runpytest_subprocess()
def test_crash_during_shutdown_captured(pytester: Pytester) -> None:
"""
Re-enable faulthandler if pytest encountered it enabled during configure.
We should be able to then see crashes during interpreter shutdown.
"""
setup_crashing_test(pytester)
args = (sys.executable, "-Xfaulthandler", "-mpytest")
result = pytester.run(*args)
result.stderr.fnmatch_lines(["*Fatal Python error*"]) result.stderr.fnmatch_lines(["*Fatal Python error*"])
assert result.ret != 0 assert result.ret != 0
def test_crash_during_shutdown_not_captured(pytester: Pytester) -> None:
"""
Check that pytest leaves faulthandler disabled if it was not enabled during configure.
This prevents us from seeing crashes during interpreter shutdown (see #8260).
"""
setup_crashing_test(pytester)
args = (sys.executable, "-mpytest")
result = pytester.run(*args)
result.stderr.no_fnmatch_line("*Fatal Python error*")
assert result.ret != 0
def test_disabled(pytester: Pytester) -> None: def test_disabled(pytester: Pytester) -> None:
"""Test option to disable fault handler in the command line.""" """Test option to disable fault handler in the command line."""
pytester.makepyfile( pytester.makepyfile(