summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/_pytest/faulthandler.py9
-rw-r--r--testing/test_faulthandler.py37
2 files changed, 33 insertions, 13 deletions
diff --git a/src/_pytest/faulthandler.py b/src/_pytest/faulthandler.py
index 9592de82d..c8eb03101 100644
--- a/src/_pytest/faulthandler.py
+++ b/src/_pytest/faulthandler.py
@@ -12,6 +12,7 @@ from _pytest.store import StoreKey
fault_handler_stderr_key = StoreKey[TextIO]()
+fault_handler_originally_enabled_key = StoreKey[bool]()
def pytest_addoption(parser: Parser) -> None:
@@ -27,6 +28,7 @@ def pytest_configure(config: Config) -> None:
stderr_fd_copy = os.dup(get_stderr_fileno())
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])
@@ -38,10 +40,9 @@ def pytest_unconfigure(config: Config) -> None:
if fault_handler_stderr_key in config._store:
config._store[fault_handler_stderr_key].close()
del config._store[fault_handler_stderr_key]
- # Re-enable the faulthandler, attaching it to the default sys.stderr
- # so we can see crashes after pytest has finished, usually during
- # garbage collection during interpreter shutdown.
- faulthandler.enable(file=get_stderr_fileno())
+ if config._store.get(fault_handler_originally_enabled_key, False):
+ # Re-enable the faulthandler if it was originally enabled.
+ faulthandler.enable(file=get_stderr_fileno())
def get_stderr_fileno() -> int:
diff --git a/testing/test_faulthandler.py b/testing/test_faulthandler.py
index 411e841a3..5b7911f21 100644
--- a/testing/test_faulthandler.py
+++ b/testing/test_faulthandler.py
@@ -19,22 +19,41 @@ def test_enabled(pytester: Pytester) -> None:
assert result.ret != 0
-def test_crash_near_exit(pytester: Pytester) -> None:
- """Test that fault handler displays crashes that happen even after
- pytest is exiting (for example, when the interpreter is shutting down)."""
+def setup_crashing_test(pytester: Pytester) -> None:
pytester.makepyfile(
"""
- import faulthandler
- import atexit
- def test_ok():
- atexit.register(faulthandler._sigabrt)
- """
+ import faulthandler
+ import atexit
+ def test_ok():
+ 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*"])
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:
"""Test option to disable fault handler in the command line."""
pytester.makepyfile(