Skip to content

Commit d2045ce

Browse files
committed
avoid keeping unraisable.object alive while waiting for collection
1 parent 7f30217 commit d2045ce

File tree

1 file changed

+25
-21
lines changed

1 file changed

+25
-21
lines changed

src/_pytest/unraisableexception.py

Lines changed: 25 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -46,9 +46,9 @@ def _tracemalloc_msg(source: object) -> str:
4646

4747

4848
class UnraisableMeta(NamedTuple):
49-
object_repr: str
50-
tracemalloc_tb: str
51-
unraisable: sys.UnraisableHookArgs
49+
msg: str
50+
cause_msg: str
51+
exc_value: BaseException | None
5252

5353

5454
def unraisable_exception_runtest_hook() -> Generator[None]:
@@ -71,27 +71,15 @@ def collect_unraisable() -> None:
7171
except IndexError:
7272
break
7373

74-
if meta.unraisable.err_msg is not None:
75-
err_msg = meta.unraisable.err_msg
76-
else:
77-
err_msg = "Exception ignored in"
78-
summary = f"{err_msg}: {meta.object_repr}"
79-
traceback_message = "\n\n" + "".join(
80-
traceback.format_exception(
81-
meta.unraisable.exc_type,
82-
meta.unraisable.exc_value,
83-
meta.unraisable.exc_traceback,
84-
)
85-
)
86-
msg = summary + traceback_message + meta.tracemalloc_tb
74+
msg = meta.msg
8775
try:
8876
warnings.warn(pytest.PytestUnraisableExceptionWarning(msg))
8977
except pytest.PytestUnraisableExceptionWarning as e:
9078
# exceptions have a better way to show the traceback, but
9179
# warnings do not, so hide the traceback from the msg and
9280
# set the cause so the traceback shows up in the right place
93-
e.args = (summary + meta.tracemalloc_tb,)
94-
e.__cause__ = meta.unraisable.exc_value
81+
e.args = (meta.cause_msg,)
82+
e.__cause__ = meta.exc_value
9583
errors.append(e)
9684

9785
if len(errors) == 1:
@@ -112,14 +100,30 @@ def _cleanup(prev_hook: Callable[[sys.UnraisableHookArgs], object]) -> None:
112100

113101

114102
def unraisable_hook(unraisable: sys.UnraisableHookArgs) -> None:
103+
if unraisable.err_msg is not None:
104+
err_msg = unraisable.err_msg
105+
else:
106+
err_msg = "Exception ignored in"
107+
summary = f"{err_msg}: {unraisable.object!r}"
108+
traceback_message = "\n\n" + "".join(
109+
traceback.format_exception(
110+
unraisable.exc_type,
111+
unraisable.exc_value,
112+
unraisable.exc_traceback,
113+
)
114+
)
115+
tracemalloc_tb = _tracemalloc_msg(unraisable.object)
116+
msg = summary + traceback_message + tracemalloc_tb
117+
cause_msg = summary + tracemalloc_tb
118+
115119
_unraisable_exceptions.append(
116120
UnraisableMeta(
117121
# we need to compute these strings here as they might change after
118122
# the unraisablehook finishes and before the unraisable object is
119123
# collected by a hook
120-
object_repr=repr(unraisable.object),
121-
tracemalloc_tb=_tracemalloc_msg(unraisable.object),
122-
unraisable=unraisable,
124+
msg=msg,
125+
cause_msg=cause_msg,
126+
exc_value=unraisable.exc_value,
123127
)
124128
)
125129

0 commit comments

Comments
 (0)