From 76f7716e86169b619f17b82a78fc61d0d72ddf11 Mon Sep 17 00:00:00 2001 From: Tian Gao Date: Wed, 25 Sep 2024 17:26:45 -0700 Subject: [PATCH 1/9] Add clear_tool_id function to unregister events and callbacks associated with tool_id --- Doc/library/sys.monitoring.rst | 12 +++-- Include/cpython/code.h | 3 ++ Include/internal/pycore_interp.h | 1 + Lib/test/test_monitoring.py | 24 ++++++++++ Python/clinic/instrumentation.c.h | 29 +++++++++++- Python/instrumentation.c | 74 +++++++++++++++++++++++++++++++ 6 files changed, 135 insertions(+), 8 deletions(-) diff --git a/Doc/library/sys.monitoring.rst b/Doc/library/sys.monitoring.rst index ac8bcceaca5aebd..f7140af2494898c 100644 --- a/Doc/library/sys.monitoring.rst +++ b/Doc/library/sys.monitoring.rst @@ -50,16 +50,14 @@ Registering and using tools *tool_id* must be in the range 0 to 5 inclusive. Raises a :exc:`ValueError` if *tool_id* is in use. -.. function:: free_tool_id(tool_id: int, /) -> None +.. function:: clear_tool_id(tool_id: int, /) -> None - Should be called once a tool no longer requires *tool_id*. + Unregister all events and callback functions associated with *tool_id*. -.. note:: +.. function:: free_tool_id(tool_id: int, /) -> None - :func:`free_tool_id` will not disable global or local events associated - with *tool_id*, nor will it unregister any callback functions. This - function is only intended to be used to notify the VM that the - particular *tool_id* is no longer in use. + Should be called once a tool no longer requires *tool_id*. + Will call :func:`clear_tool_id` before releasing *tool_id*. .. function:: get_tool(tool_id: int, /) -> str | None diff --git a/Include/cpython/code.h b/Include/cpython/code.h index 58d93fcfc1066ba..bae0b60d9a17ca3 100644 --- a/Include/cpython/code.h +++ b/Include/cpython/code.h @@ -8,6 +8,8 @@ extern "C" { #endif +/* Total tool ids available */ +#define _PY_MONITORING_TOOL_IDS 8 /* Count of all local monitoring events */ #define _PY_MONITORING_LOCAL_EVENTS 10 /* Count of all "real" monitoring events (not derived from other events) */ @@ -18,6 +20,7 @@ extern "C" { /* Tables of which tools are active for each monitored event. */ typedef struct _Py_LocalMonitors { uint8_t tools[_PY_MONITORING_LOCAL_EVENTS]; + uintptr_t tool_versions[_PY_MONITORING_TOOL_IDS]; } _Py_LocalMonitors; typedef struct _Py_GlobalMonitors { diff --git a/Include/internal/pycore_interp.h b/Include/internal/pycore_interp.h index 36366429e8db25d..497f2d7319c8ccd 100644 --- a/Include/internal/pycore_interp.h +++ b/Include/internal/pycore_interp.h @@ -272,6 +272,7 @@ struct _is { Py_ssize_t sys_tracing_threads; /* Count of threads with c_tracefunc set */ PyObject *monitoring_callables[PY_MONITORING_TOOL_IDS][_PY_MONITORING_EVENTS]; PyObject *monitoring_tool_names[PY_MONITORING_TOOL_IDS]; + uintptr_t monitoring_tool_versions[PY_MONITORING_TOOL_IDS]; struct _Py_interp_cached_objects cached_objects; struct _Py_interp_static_objects static_objects; diff --git a/Lib/test/test_monitoring.py b/Lib/test/test_monitoring.py index 351f1067c103435..377f0fe9d47db19 100644 --- a/Lib/test/test_monitoring.py +++ b/Lib/test/test_monitoring.py @@ -50,6 +50,7 @@ def test_has_objects(self): m = sys.monitoring m.events m.use_tool_id + m.clear_tool_id m.free_tool_id m.get_tool m.get_events @@ -77,6 +78,29 @@ def test_tool(self): with self.assertRaises(ValueError): sys.monitoring.set_events(TEST_TOOL, sys.monitoring.events.CALL) + def test_clear(self): + events = [] + sys.monitoring.use_tool_id(TEST_TOOL, "MonitoringTest.Tool") + sys.monitoring.register_callback(TEST_TOOL, E.PY_START, lambda *args: events.append(args)) + sys.monitoring.register_callback(TEST_TOOL, E.LINE, lambda *args: events.append(args)) + def f(): + a = 1 + sys.monitoring.set_local_events(TEST_TOOL, f.__code__, E.LINE) + sys.monitoring.set_events(TEST_TOOL, E.PY_START) + + f() + sys.monitoring.clear_tool_id(TEST_TOOL) + f() + + # the first f() should trigger a PY_START and a LINE event + # the second f() after clear_tool_id should not trigger any event + # the callback function should be cleared as well + self.assertEqual(len(events), 2) + callback = sys.monitoring.register_callback(TEST_TOOL, E.LINE, None) + self.assertIs(callback, None) + + sys.monitoring.free_tool_id(TEST_TOOL) + class MonitoringTestBase: diff --git a/Python/clinic/instrumentation.c.h b/Python/clinic/instrumentation.c.h index 8dae747c44a543d..9b3373bc1a67a5d 100644 --- a/Python/clinic/instrumentation.c.h +++ b/Python/clinic/instrumentation.c.h @@ -36,6 +36,33 @@ monitoring_use_tool_id(PyObject *module, PyObject *const *args, Py_ssize_t nargs return return_value; } +PyDoc_STRVAR(monitoring_clear_tool_id__doc__, +"clear_tool_id($module, tool_id, /)\n" +"--\n" +"\n"); + +#define MONITORING_CLEAR_TOOL_ID_METHODDEF \ + {"clear_tool_id", (PyCFunction)monitoring_clear_tool_id, METH_O, monitoring_clear_tool_id__doc__}, + +static PyObject * +monitoring_clear_tool_id_impl(PyObject *module, int tool_id); + +static PyObject * +monitoring_clear_tool_id(PyObject *module, PyObject *arg) +{ + PyObject *return_value = NULL; + int tool_id; + + tool_id = PyLong_AsInt(arg); + if (tool_id == -1 && PyErr_Occurred()) { + goto exit; + } + return_value = monitoring_clear_tool_id_impl(module, tool_id); + +exit: + return return_value; +} + PyDoc_STRVAR(monitoring_free_tool_id__doc__, "free_tool_id($module, tool_id, /)\n" "--\n" @@ -304,4 +331,4 @@ monitoring__all_events(PyObject *module, PyObject *Py_UNUSED(ignored)) { return monitoring__all_events_impl(module); } -/*[clinic end generated code: output=14ffc0884a6de50a input=a9049054013a1b77]*/ +/*[clinic end generated code: output=8f81876c6aba9be8 input=a9049054013a1b77]*/ diff --git a/Python/instrumentation.c b/Python/instrumentation.c index 5e51a9c992f6c2d..5b8757859d52556 100644 --- a/Python/instrumentation.c +++ b/Python/instrumentation.c @@ -1660,6 +1660,15 @@ update_instrumentation_data(PyCodeObject *code, PyInterpreterState *interp) if (allocate_instrumentation_data(code)) { return -1; } + // If the local monitors are out of date, clear them up + _Py_LocalMonitors *local_monitors = &code->_co_monitoring->local_monitors; + for (int i = 0; i < PY_MONITORING_TOOL_IDS; i++) { + if (local_monitors->tool_versions[i] != interp->monitoring_tool_versions[i]) { + for (int j = 0; j < _PY_MONITORING_LOCAL_EVENTS; j++) { + local_monitors->tools[j] &= ~(1 << i); + } + } + } _Py_LocalMonitors all_events = local_union( interp->monitors, code->_co_monitoring->local_monitors); @@ -2011,6 +2020,7 @@ _PyMonitoring_SetLocalEvents(PyCodeObject *code, int tool_id, _PyMonitoringEvent goto done; } set_local_events(local, tool_id, events); + local->tool_versions[tool_id] = interp->monitoring_tool_versions[tool_id]; res = force_instrument_lock_held(code, interp); @@ -2036,6 +2046,35 @@ _PyMonitoring_GetLocalEvents(PyCodeObject *code, int tool_id, _PyMonitoringEvent return 0; } +int _PyMonitoring_ClearToolId(int tool_id) +{ + assert(0 <= tool_id && tool_id < PY_MONITORING_TOOL_IDS); + PyInterpreterState *interp = _PyInterpreterState_GET(); + + for (int i = 0; i < _PY_MONITORING_EVENTS; i++) { + PyObject *func = _PyMonitoring_RegisterCallback(tool_id, i, NULL); + if (func != NULL) { + Py_DECREF(func); + } + } + + if (_PyMonitoring_SetEvents(tool_id, 0) < 0) { + return -1; + } + + _PyEval_StopTheWorld(interp); + uint32_t version = global_version(interp) + MONITORING_VERSION_INCREMENT; + if (version == 0) { + PyErr_Format(PyExc_OverflowError, "events set too many times"); + _PyEval_StartTheWorld(interp); + return -1; + } + interp->monitoring_tool_versions[tool_id] = version; + set_global_version(_PyThreadState_GET(), version); + _PyEval_StartTheWorld(interp); + return 0; +} + /*[clinic input] module monitoring [clinic start generated code]*/ @@ -2083,6 +2122,33 @@ monitoring_use_tool_id_impl(PyObject *module, int tool_id, PyObject *name) Py_RETURN_NONE; } +/*[clinic input] +monitoring.clear_tool_id + + tool_id: int + / + +[clinic start generated code]*/ + +static PyObject * +monitoring_clear_tool_id_impl(PyObject *module, int tool_id) +/*[clinic end generated code: output=04defc23470b1be7 input=af643d6648a66163]*/ +{ + if (check_valid_tool(tool_id)) { + return NULL; + } + + PyInterpreterState *interp = _PyInterpreterState_GET(); + + if (interp->monitoring_tool_names[tool_id] != NULL) { + if (_PyMonitoring_ClearToolId(tool_id) < 0) { + return NULL; + } + } + + Py_RETURN_NONE; +} + /*[clinic input] monitoring.free_tool_id @@ -2099,6 +2165,13 @@ monitoring_free_tool_id_impl(PyObject *module, int tool_id) return NULL; } PyInterpreterState *interp = _PyInterpreterState_GET(); + + if (interp->monitoring_tool_names[tool_id] != NULL) { + if (_PyMonitoring_ClearToolId(tool_id) < 0) { + return NULL; + } + } + Py_CLEAR(interp->monitoring_tool_names[tool_id]); Py_RETURN_NONE; } @@ -2376,6 +2449,7 @@ monitoring__all_events_impl(PyObject *module) static PyMethodDef methods[] = { MONITORING_USE_TOOL_ID_METHODDEF + MONITORING_CLEAR_TOOL_ID_METHODDEF MONITORING_FREE_TOOL_ID_METHODDEF MONITORING_GET_TOOL_METHODDEF MONITORING_REGISTER_CALLBACK_METHODDEF From 81e1de04da134a95dd55ac0e0d5d3099c16dd1fd Mon Sep 17 00:00:00 2001 From: "blurb-it[bot]" <43283697+blurb-it[bot]@users.noreply.github.com> Date: Thu, 26 Sep 2024 00:35:26 +0000 Subject: [PATCH 2/9] =?UTF-8?q?=F0=9F=93=9C=F0=9F=A4=96=20Added=20by=20blu?= =?UTF-8?q?rb=5Fit.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../next/Library/2024-09-26-00-35-24.gh-issue-116750.X1aMHI.rst | 1 + 1 file changed, 1 insertion(+) create mode 100644 Misc/NEWS.d/next/Library/2024-09-26-00-35-24.gh-issue-116750.X1aMHI.rst diff --git a/Misc/NEWS.d/next/Library/2024-09-26-00-35-24.gh-issue-116750.X1aMHI.rst b/Misc/NEWS.d/next/Library/2024-09-26-00-35-24.gh-issue-116750.X1aMHI.rst new file mode 100644 index 000000000000000..cf9dacf4007c289 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2024-09-26-00-35-24.gh-issue-116750.X1aMHI.rst @@ -0,0 +1 @@ +Provide :func:`sys.monitoring.clear_tool_id` to unregister all events and callbacks set by the tool. From 6d1dfa9b5a6b474acbf7768bd9552aea8b532814 Mon Sep 17 00:00:00 2001 From: Tian Gao Date: Thu, 26 Sep 2024 10:38:45 -0700 Subject: [PATCH 3/9] Move tool version to code monitoring and force an instrument --- Include/cpython/code.h | 3 ++- Python/instrumentation.c | 9 ++++++--- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/Include/cpython/code.h b/Include/cpython/code.h index bae0b60d9a17ca3..03622698113ee7d 100644 --- a/Include/cpython/code.h +++ b/Include/cpython/code.h @@ -20,7 +20,6 @@ extern "C" { /* Tables of which tools are active for each monitored event. */ typedef struct _Py_LocalMonitors { uint8_t tools[_PY_MONITORING_LOCAL_EVENTS]; - uintptr_t tool_versions[_PY_MONITORING_TOOL_IDS]; } _Py_LocalMonitors; typedef struct _Py_GlobalMonitors { @@ -60,6 +59,8 @@ typedef struct { _Py_LocalMonitors active_monitors; /* The tools that are to be notified for events for the matching code unit */ uint8_t *tools; + /* The version of tools when they instrument the code */ + uintptr_t tool_versions[_PY_MONITORING_TOOL_IDS]; /* Information to support line events */ _PyCoLineInstrumentationData *lines; /* The tools that are to be notified for line events for the matching code unit */ diff --git a/Python/instrumentation.c b/Python/instrumentation.c index 5b8757859d52556..157f3d1a8525db4 100644 --- a/Python/instrumentation.c +++ b/Python/instrumentation.c @@ -1663,12 +1663,13 @@ update_instrumentation_data(PyCodeObject *code, PyInterpreterState *interp) // If the local monitors are out of date, clear them up _Py_LocalMonitors *local_monitors = &code->_co_monitoring->local_monitors; for (int i = 0; i < PY_MONITORING_TOOL_IDS; i++) { - if (local_monitors->tool_versions[i] != interp->monitoring_tool_versions[i]) { + if (code->_co_monitoring->tool_versions[i] != interp->monitoring_tool_versions[i]) { for (int j = 0; j < _PY_MONITORING_LOCAL_EVENTS; j++) { local_monitors->tools[j] &= ~(1 << i); } } } + _Py_LocalMonitors all_events = local_union( interp->monitors, code->_co_monitoring->local_monitors); @@ -2013,6 +2014,8 @@ _PyMonitoring_SetLocalEvents(PyCodeObject *code, int tool_id, _PyMonitoringEvent goto done; } + code->_co_monitoring->tool_versions[tool_id] = interp->monitoring_tool_versions[tool_id]; + _Py_LocalMonitors *local = &code->_co_monitoring->local_monitors; uint32_t existing_events = get_local_events(local, tool_id); if (existing_events == events) { @@ -2020,7 +2023,6 @@ _PyMonitoring_SetLocalEvents(PyCodeObject *code, int tool_id, _PyMonitoringEvent goto done; } set_local_events(local, tool_id, events); - local->tool_versions[tool_id] = interp->monitoring_tool_versions[tool_id]; res = force_instrument_lock_held(code, interp); @@ -2071,8 +2073,9 @@ int _PyMonitoring_ClearToolId(int tool_id) } interp->monitoring_tool_versions[tool_id] = version; set_global_version(_PyThreadState_GET(), version); + int res = instrument_all_executing_code_objects(interp); _PyEval_StartTheWorld(interp); - return 0; + return res; } /*[clinic input] From 529e0dfa6e6ad5c6eb5aa1b6e37422ea427fb722 Mon Sep 17 00:00:00 2001 From: Tian Gao Date: Thu, 26 Sep 2024 10:44:42 -0700 Subject: [PATCH 4/9] Initialize tool versions --- Python/pystate.c | 1 + 1 file changed, 1 insertion(+) diff --git a/Python/pystate.c b/Python/pystate.c index 6bf7ebeb75ff730..2c9d00a5c070fa5 100644 --- a/Python/pystate.c +++ b/Python/pystate.c @@ -654,6 +654,7 @@ init_interpreter(PyInterpreterState *interp, interp->monitoring_callables[t][e] = NULL; } + interp->monitoring_tool_versions[t] = 0; } interp->sys_profile_initialized = false; interp->sys_trace_initialized = false; From 151e3b357a0120755fbd78f578a35a6dc34d8508 Mon Sep 17 00:00:00 2001 From: Tian Gao Date: Fri, 27 Sep 2024 15:32:08 -0700 Subject: [PATCH 5/9] Add an extra test for use after free --- Lib/test/test_monitoring.py | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/Lib/test/test_monitoring.py b/Lib/test/test_monitoring.py index 377f0fe9d47db19..2a326684460b991 100644 --- a/Lib/test/test_monitoring.py +++ b/Lib/test/test_monitoring.py @@ -46,6 +46,9 @@ def nth_line(func, offset): class MonitoringBasicTest(unittest.TestCase): + def tearDown(self): + sys.monitoring.free_tool_id(TEST_TOOL) + def test_has_objects(self): m = sys.monitoring m.events @@ -101,6 +104,20 @@ def f(): sys.monitoring.free_tool_id(TEST_TOOL) + events = [] + sys.monitoring.use_tool_id(TEST_TOOL, "MonitoringTest.Tool") + sys.monitoring.register_callback(TEST_TOOL, E.LINE, lambda *args: events.append(args)) + sys.monitoring.set_local_events(TEST_TOOL, f.__code__, E.LINE) + f() + sys.monitoring.free_tool_id(TEST_TOOL) + sys.monitoring.use_tool_id(TEST_TOOL, "MonitoringTest.Tool") + f() + # the first f() should trigger a LINE event, and even if we use the + # tool id immediately after freeing it, the second f() should not + # trigger any event + self.assertEqual(len(events), 1) + sys.monitoring.free_tool_id(TEST_TOOL) + class MonitoringTestBase: From 5fb656e05b3988509b4434477800db5ec0bc5c65 Mon Sep 17 00:00:00 2001 From: Tian Gao Date: Fri, 27 Sep 2024 15:47:29 -0700 Subject: [PATCH 6/9] Add comments --- Python/instrumentation.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/Python/instrumentation.c b/Python/instrumentation.c index 157f3d1a8525db4..d9ea412872ff079 100644 --- a/Python/instrumentation.c +++ b/Python/instrumentation.c @@ -2071,7 +2071,14 @@ int _PyMonitoring_ClearToolId(int tool_id) _PyEval_StartTheWorld(interp); return -1; } + + // monitoring_tool_versions[tool_id] is set to latest global version here to + // 1. invalidate local events on all existing code objects + // 2. be ready for the next use_tool_id call so we can only do this in one place interp->monitoring_tool_versions[tool_id] = version; + + // Set the new global version so all the code objects can refresh the + // instrumentation. set_global_version(_PyThreadState_GET(), version); int res = instrument_all_executing_code_objects(interp); _PyEval_StartTheWorld(interp); From fd74a550d6626977a39f101e2460e130ac00b7ea Mon Sep 17 00:00:00 2001 From: Tian Gao Date: Fri, 27 Sep 2024 15:54:27 -0700 Subject: [PATCH 7/9] Only set tool verions for external tool ids --- Include/cpython/code.h | 6 +++--- Include/internal/pycore_interp.h | 3 ++- Python/instrumentation.c | 2 +- Python/pystate.c | 2 ++ 4 files changed, 8 insertions(+), 5 deletions(-) diff --git a/Include/cpython/code.h b/Include/cpython/code.h index 03622698113ee7d..f4dd75bf41be2d5 100644 --- a/Include/cpython/code.h +++ b/Include/cpython/code.h @@ -8,8 +8,8 @@ extern "C" { #endif -/* Total tool ids available */ -#define _PY_MONITORING_TOOL_IDS 8 +/* Total tool ids available for external use */ +#define _PY_MONITORING_EXTENAL_TOOL_IDS 6 /* Count of all local monitoring events */ #define _PY_MONITORING_LOCAL_EVENTS 10 /* Count of all "real" monitoring events (not derived from other events) */ @@ -60,7 +60,7 @@ typedef struct { /* The tools that are to be notified for events for the matching code unit */ uint8_t *tools; /* The version of tools when they instrument the code */ - uintptr_t tool_versions[_PY_MONITORING_TOOL_IDS]; + uintptr_t tool_versions[_PY_MONITORING_EXTENAL_TOOL_IDS]; /* Information to support line events */ _PyCoLineInstrumentationData *lines; /* The tools that are to be notified for line events for the matching code unit */ diff --git a/Include/internal/pycore_interp.h b/Include/internal/pycore_interp.h index 497f2d7319c8ccd..75a12b622ebd72d 100644 --- a/Include/internal/pycore_interp.h +++ b/Include/internal/pycore_interp.h @@ -272,7 +272,8 @@ struct _is { Py_ssize_t sys_tracing_threads; /* Count of threads with c_tracefunc set */ PyObject *monitoring_callables[PY_MONITORING_TOOL_IDS][_PY_MONITORING_EVENTS]; PyObject *monitoring_tool_names[PY_MONITORING_TOOL_IDS]; - uintptr_t monitoring_tool_versions[PY_MONITORING_TOOL_IDS]; + // Only external available tool ids need versioning. + uintptr_t monitoring_tool_versions[PY_MONITORING_SYS_PROFILE_ID]; struct _Py_interp_cached_objects cached_objects; struct _Py_interp_static_objects static_objects; diff --git a/Python/instrumentation.c b/Python/instrumentation.c index d9ea412872ff079..7e7af2cc694766c 100644 --- a/Python/instrumentation.c +++ b/Python/instrumentation.c @@ -1662,7 +1662,7 @@ update_instrumentation_data(PyCodeObject *code, PyInterpreterState *interp) } // If the local monitors are out of date, clear them up _Py_LocalMonitors *local_monitors = &code->_co_monitoring->local_monitors; - for (int i = 0; i < PY_MONITORING_TOOL_IDS; i++) { + for (int i = 0; i < PY_MONITORING_SYS_PROFILE_ID; i++) { if (code->_co_monitoring->tool_versions[i] != interp->monitoring_tool_versions[i]) { for (int j = 0; j < _PY_MONITORING_LOCAL_EVENTS; j++) { local_monitors->tools[j] &= ~(1 << i); diff --git a/Python/pystate.c b/Python/pystate.c index 2c9d00a5c070fa5..cdbbe5a4041d76a 100644 --- a/Python/pystate.c +++ b/Python/pystate.c @@ -654,6 +654,8 @@ init_interpreter(PyInterpreterState *interp, interp->monitoring_callables[t][e] = NULL; } + } + for (int t = 0; t < PY_MONITORING_SYS_PROFILE_ID; t++) { interp->monitoring_tool_versions[t] = 0; } interp->sys_profile_initialized = false; From 82b42ec3fed0d189020d2fc8e673572b12b366c2 Mon Sep 17 00:00:00 2001 From: Tian Gao Date: Fri, 27 Sep 2024 15:56:39 -0700 Subject: [PATCH 8/9] Revert "Only set tool verions for external tool ids" This reverts commit fd74a550d6626977a39f101e2460e130ac00b7ea. --- Include/cpython/code.h | 6 +++--- Include/internal/pycore_interp.h | 3 +-- Python/instrumentation.c | 2 +- Python/pystate.c | 2 -- 4 files changed, 5 insertions(+), 8 deletions(-) diff --git a/Include/cpython/code.h b/Include/cpython/code.h index f4dd75bf41be2d5..03622698113ee7d 100644 --- a/Include/cpython/code.h +++ b/Include/cpython/code.h @@ -8,8 +8,8 @@ extern "C" { #endif -/* Total tool ids available for external use */ -#define _PY_MONITORING_EXTENAL_TOOL_IDS 6 +/* Total tool ids available */ +#define _PY_MONITORING_TOOL_IDS 8 /* Count of all local monitoring events */ #define _PY_MONITORING_LOCAL_EVENTS 10 /* Count of all "real" monitoring events (not derived from other events) */ @@ -60,7 +60,7 @@ typedef struct { /* The tools that are to be notified for events for the matching code unit */ uint8_t *tools; /* The version of tools when they instrument the code */ - uintptr_t tool_versions[_PY_MONITORING_EXTENAL_TOOL_IDS]; + uintptr_t tool_versions[_PY_MONITORING_TOOL_IDS]; /* Information to support line events */ _PyCoLineInstrumentationData *lines; /* The tools that are to be notified for line events for the matching code unit */ diff --git a/Include/internal/pycore_interp.h b/Include/internal/pycore_interp.h index 75a12b622ebd72d..497f2d7319c8ccd 100644 --- a/Include/internal/pycore_interp.h +++ b/Include/internal/pycore_interp.h @@ -272,8 +272,7 @@ struct _is { Py_ssize_t sys_tracing_threads; /* Count of threads with c_tracefunc set */ PyObject *monitoring_callables[PY_MONITORING_TOOL_IDS][_PY_MONITORING_EVENTS]; PyObject *monitoring_tool_names[PY_MONITORING_TOOL_IDS]; - // Only external available tool ids need versioning. - uintptr_t monitoring_tool_versions[PY_MONITORING_SYS_PROFILE_ID]; + uintptr_t monitoring_tool_versions[PY_MONITORING_TOOL_IDS]; struct _Py_interp_cached_objects cached_objects; struct _Py_interp_static_objects static_objects; diff --git a/Python/instrumentation.c b/Python/instrumentation.c index 7e7af2cc694766c..d9ea412872ff079 100644 --- a/Python/instrumentation.c +++ b/Python/instrumentation.c @@ -1662,7 +1662,7 @@ update_instrumentation_data(PyCodeObject *code, PyInterpreterState *interp) } // If the local monitors are out of date, clear them up _Py_LocalMonitors *local_monitors = &code->_co_monitoring->local_monitors; - for (int i = 0; i < PY_MONITORING_SYS_PROFILE_ID; i++) { + for (int i = 0; i < PY_MONITORING_TOOL_IDS; i++) { if (code->_co_monitoring->tool_versions[i] != interp->monitoring_tool_versions[i]) { for (int j = 0; j < _PY_MONITORING_LOCAL_EVENTS; j++) { local_monitors->tools[j] &= ~(1 << i); diff --git a/Python/pystate.c b/Python/pystate.c index cdbbe5a4041d76a..2c9d00a5c070fa5 100644 --- a/Python/pystate.c +++ b/Python/pystate.c @@ -654,8 +654,6 @@ init_interpreter(PyInterpreterState *interp, interp->monitoring_callables[t][e] = NULL; } - } - for (int t = 0; t < PY_MONITORING_SYS_PROFILE_ID; t++) { interp->monitoring_tool_versions[t] = 0; } interp->sys_profile_initialized = false; From 9986702852981d2609d11220716e9268189261d8 Mon Sep 17 00:00:00 2001 From: Tian Gao Date: Sun, 29 Sep 2024 22:07:15 -0400 Subject: [PATCH 9/9] Update comments --- Python/instrumentation.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Python/instrumentation.c b/Python/instrumentation.c index d9ea412872ff079..8fd7c08beac92a1 100644 --- a/Python/instrumentation.c +++ b/Python/instrumentation.c @@ -2074,7 +2074,7 @@ int _PyMonitoring_ClearToolId(int tool_id) // monitoring_tool_versions[tool_id] is set to latest global version here to // 1. invalidate local events on all existing code objects - // 2. be ready for the next use_tool_id call so we can only do this in one place + // 2. be ready for the next call to set local events interp->monitoring_tool_versions[tool_id] = version; // Set the new global version so all the code objects can refresh the