Only re-enable fauthandler during unconfigure if it was enabled before
This commit is contained in:
parent
adc0f29b8f
commit
33861098d9
|
@ -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:
|
||||||
|
|
|
@ -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(
|
||||||
|
|
Loading…
Reference in New Issue