diff options
author | Brett Simmers <swtaarrs@users.noreply.github.com> | 2024-03-04 08:29:39 -0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-03-04 11:29:39 -0500 |
commit | 0adfa8482d369899e9963206a3307f423309e10c (patch) | |
tree | c1f71c0f65b0f01581d37eafa55c26b769915299 /Lib/test/_test_monitoring_shutdown.py | |
parent | 15dc2979bc1b24269177f0e150495abb7f3eb546 (diff) | |
download | cpython-0adfa8482d369899e9963206a3307f423309e10c.tar.gz cpython-0adfa8482d369899e9963206a3307f423309e10c.zip |
gh-115832: Fix instrumentation version mismatch during interpreter shutdown (#115856)
A previous commit introduced a bug to `interpreter_clear()`: it set
`interp->ceval.instrumentation_version` to 0, without making the corresponding
change to `tstate->eval_breaker` (which holds a thread-local copy of the
version). After this happens, Python code can still run due to object finalizers
during a GC, and the version check in bytecodes.c will see a different result
than the one in instrumentation.c causing an infinite loop.
The fix itself is straightforward: clear `tstate->eval_breaker` when clearing
`interp->ceval.instrumentation_version`.
Diffstat (limited to 'Lib/test/_test_monitoring_shutdown.py')
-rw-r--r-- | Lib/test/_test_monitoring_shutdown.py | 30 |
1 files changed, 30 insertions, 0 deletions
diff --git a/Lib/test/_test_monitoring_shutdown.py b/Lib/test/_test_monitoring_shutdown.py new file mode 100644 index 00000000000..3d0fbec029d --- /dev/null +++ b/Lib/test/_test_monitoring_shutdown.py @@ -0,0 +1,30 @@ +#!/usr/bin/env python3 + +# gh-115832: An object destructor running during the final GC of interpreter +# shutdown triggered an infinite loop in the instrumentation code. + +import sys + +class CallableCycle: + def __init__(self): + self._cycle = self + + def __del__(self): + pass + + def __call__(self, code, instruction_offset): + pass + +def tracefunc(frame, event, arg): + pass + +def main(): + tool_id = sys.monitoring.PROFILER_ID + event_id = sys.monitoring.events.PY_START + + sys.monitoring.use_tool_id(tool_id, "test profiler") + sys.monitoring.set_events(tool_id, event_id) + sys.monitoring.register_callback(tool_id, event_id, CallableCycle()) + +if __name__ == "__main__": + sys.exit(main()) |