Skip to content

Commit 8f8ca16

Browse files
committed
gh-159117: Preserve sys.setprofile callbacks when destroying a tracing profiler
1 parent 2188f9b commit 8f8ca16

3 files changed

Lines changed: 18 additions & 9 deletions

File tree

‎Lib/test/test_profiling/test_tracing_profiler.py‎

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,22 @@ def test_profile_enable_disable(self):
118118
prof.disable()
119119
self.assertIs(sys.monitoring.get_tool(sys.monitoring.PROFILER_ID), None)
120120

121+
def test_dealloc_does_not_disable_sys_profile(self):
122+
self.addCleanup(sys.setprofile, sys.getprofile())
123+
self.addCleanup(sys.monitoring.free_tool_id, sys.monitoring.PROFILER_ID)
124+
125+
def callback(frame, event, arg):
126+
pass
127+
128+
prof = self.profilerclass()
129+
prof.enable()
130+
sys.setprofile(callback)
131+
# Release the monitoring callbacks so the enabled profiler can be
132+
# destroyed without an explicit disable().
133+
sys.monitoring.free_tool_id(sys.monitoring.PROFILER_ID)
134+
del prof
135+
self.assertIs(sys.getprofile(), callback)
136+
121137
def test_profile_as_context_manager(self):
122138
prof = self.profilerclass()
123139
# Make sure we clean ourselves up if the test fails for some reason.
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Prevent deallocation of a :mod:`profiling.tracing` profiler from disabling an
2+
unrelated :func:`sys.setprofile` callback.

‎Modules/_lsprof.c‎

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,6 @@
44

55
#include "Python.h"
66
#include "pycore_call.h" // _PyObject_CallNoArgs()
7-
#include "pycore_ceval.h" // _PyEval_SetProfile()
8-
#include "pycore_pystate.h" // _PyThreadState_GET()
97
#include "pycore_time.h" // _PyTime_FromSecondsObject()
108
#include "pycore_typeobject.h" // _PyType_GetModuleState()
119
#include "pycore_unicodeobject.h" // _PyUnicode_EqualToASCIIString()
@@ -982,13 +980,6 @@ profiler_dealloc(PyObject *op)
982980
{
983981
ProfilerObject *self = ProfilerObject_CAST(op);
984982
PyObject_GC_UnTrack(self);
985-
if (self->flags & POF_ENABLED) {
986-
PyThreadState *tstate = _PyThreadState_GET();
987-
if (_PyEval_SetProfile(tstate, NULL, NULL) < 0) {
988-
PyErr_FormatUnraisable("Exception ignored while "
989-
"destroying _lsprof profiler");
990-
}
991-
}
992983

993984
/* Drop the external timer before flushing: it is Python code, and the
994985
profiler can be deallocated by the garbage collector. */

0 commit comments

Comments
 (0)