From e340a075e5e46ed327699d507e0d0eb17d2bc43c Mon Sep 17 00:00:00 2001 From: Simon Blanchard Date: Fri, 3 Nov 2023 21:37:10 +0100 Subject: [PATCH] remember stderr fileno in config.stash to be restored on faulthandler teardown --- changelog/11572.bugfix.rst | 1 + src/_pytest/faulthandler.py | 11 +++++++++-- 2 files changed, 10 insertions(+), 2 deletions(-) create mode 100644 changelog/11572.bugfix.rst diff --git a/changelog/11572.bugfix.rst b/changelog/11572.bugfix.rst new file mode 100644 index 000000000..7a235a071 --- /dev/null +++ b/changelog/11572.bugfix.rst @@ -0,0 +1 @@ +Handle an edge case where :data:`sys.stderr` and :data:`sys.__stderr__` might already be closed when :ref:`faulthandler` is tearing down. diff --git a/src/_pytest/faulthandler.py b/src/_pytest/faulthandler.py index a9418f34e..7780ad5e9 100644 --- a/src/_pytest/faulthandler.py +++ b/src/_pytest/faulthandler.py @@ -9,6 +9,7 @@ from _pytest.nodes import Item from _pytest.stash import StashKey +fault_handler_original_stderr_fd_key = StashKey[int]() fault_handler_stderr_fd_key = StashKey[int]() fault_handler_originally_enabled_key = StashKey[bool]() @@ -24,7 +25,9 @@ def pytest_addoption(parser: Parser) -> None: def pytest_configure(config: Config) -> None: import faulthandler - config.stash[fault_handler_stderr_fd_key] = os.dup(get_stderr_fileno()) + stderr_fileno = get_stderr_fileno() + config.stash[fault_handler_original_stderr_fd_key] = stderr_fileno + config.stash[fault_handler_stderr_fd_key] = os.dup(stderr_fileno) config.stash[fault_handler_originally_enabled_key] = faulthandler.is_enabled() faulthandler.enable(file=config.stash[fault_handler_stderr_fd_key]) @@ -39,7 +42,11 @@ def pytest_unconfigure(config: Config) -> None: del config.stash[fault_handler_stderr_fd_key] if config.stash.get(fault_handler_originally_enabled_key, False): # Re-enable the faulthandler if it was originally enabled. - faulthandler.enable(file=get_stderr_fileno()) + if fault_handler_original_stderr_fd_key in config.stash: + faulthandler.enable(config.stash[fault_handler_original_stderr_fd_key]) + del config.stash[fault_handler_original_stderr_fd_key] + else: + faulthandler.enable(file=get_stderr_fileno()) def get_stderr_fileno() -> int: