@@ -1660,6 +1660,16 @@ update_instrumentation_data(PyCodeObject *code, PyInterpreterState *interp)
16601660 if (allocate_instrumentation_data (code )) {
16611661 return -1 ;
16621662 }
1663+ // If the local monitors are out of date, clear them up
1664+ _Py_LocalMonitors * local_monitors = & code -> _co_monitoring -> local_monitors ;
1665+ for (int i = 0 ; i < PY_MONITORING_TOOL_IDS ; i ++ ) {
1666+ if (code -> _co_monitoring -> tool_versions [i ] != interp -> monitoring_tool_versions [i ]) {
1667+ for (int j = 0 ; j < _PY_MONITORING_LOCAL_EVENTS ; j ++ ) {
1668+ local_monitors -> tools [j ] &= ~(1 << i );
1669+ }
1670+ }
1671+ }
1672+
16631673 _Py_LocalMonitors all_events = local_union (
16641674 interp -> monitors ,
16651675 code -> _co_monitoring -> local_monitors );
@@ -2004,6 +2014,8 @@ _PyMonitoring_SetLocalEvents(PyCodeObject *code, int tool_id, _PyMonitoringEvent
20042014 goto done ;
20052015 }
20062016
2017+ code -> _co_monitoring -> tool_versions [tool_id ] = interp -> monitoring_tool_versions [tool_id ];
2018+
20072019 _Py_LocalMonitors * local = & code -> _co_monitoring -> local_monitors ;
20082020 uint32_t existing_events = get_local_events (local , tool_id );
20092021 if (existing_events == events ) {
@@ -2036,6 +2048,43 @@ _PyMonitoring_GetLocalEvents(PyCodeObject *code, int tool_id, _PyMonitoringEvent
20362048 return 0 ;
20372049}
20382050
2051+ int _PyMonitoring_ClearToolId (int tool_id )
2052+ {
2053+ assert (0 <= tool_id && tool_id < PY_MONITORING_TOOL_IDS );
2054+ PyInterpreterState * interp = _PyInterpreterState_GET ();
2055+
2056+ for (int i = 0 ; i < _PY_MONITORING_EVENTS ; i ++ ) {
2057+ PyObject * func = _PyMonitoring_RegisterCallback (tool_id , i , NULL );
2058+ if (func != NULL ) {
2059+ Py_DECREF (func );
2060+ }
2061+ }
2062+
2063+ if (_PyMonitoring_SetEvents (tool_id , 0 ) < 0 ) {
2064+ return -1 ;
2065+ }
2066+
2067+ _PyEval_StopTheWorld (interp );
2068+ uint32_t version = global_version (interp ) + MONITORING_VERSION_INCREMENT ;
2069+ if (version == 0 ) {
2070+ PyErr_Format (PyExc_OverflowError , "events set too many times" );
2071+ _PyEval_StartTheWorld (interp );
2072+ return -1 ;
2073+ }
2074+
2075+ // monitoring_tool_versions[tool_id] is set to latest global version here to
2076+ // 1. invalidate local events on all existing code objects
2077+ // 2. be ready for the next call to set local events
2078+ interp -> monitoring_tool_versions [tool_id ] = version ;
2079+
2080+ // Set the new global version so all the code objects can refresh the
2081+ // instrumentation.
2082+ set_global_version (_PyThreadState_GET (), version );
2083+ int res = instrument_all_executing_code_objects (interp );
2084+ _PyEval_StartTheWorld (interp );
2085+ return res ;
2086+ }
2087+
20392088/*[clinic input]
20402089module monitoring
20412090[clinic start generated code]*/
@@ -2083,6 +2132,33 @@ monitoring_use_tool_id_impl(PyObject *module, int tool_id, PyObject *name)
20832132 Py_RETURN_NONE ;
20842133}
20852134
2135+ /*[clinic input]
2136+ monitoring.clear_tool_id
2137+
2138+ tool_id: int
2139+ /
2140+
2141+ [clinic start generated code]*/
2142+
2143+ static PyObject *
2144+ monitoring_clear_tool_id_impl (PyObject * module , int tool_id )
2145+ /*[clinic end generated code: output=04defc23470b1be7 input=af643d6648a66163]*/
2146+ {
2147+ if (check_valid_tool (tool_id )) {
2148+ return NULL ;
2149+ }
2150+
2151+ PyInterpreterState * interp = _PyInterpreterState_GET ();
2152+
2153+ if (interp -> monitoring_tool_names [tool_id ] != NULL ) {
2154+ if (_PyMonitoring_ClearToolId (tool_id ) < 0 ) {
2155+ return NULL ;
2156+ }
2157+ }
2158+
2159+ Py_RETURN_NONE ;
2160+ }
2161+
20862162/*[clinic input]
20872163monitoring.free_tool_id
20882164
@@ -2099,6 +2175,13 @@ monitoring_free_tool_id_impl(PyObject *module, int tool_id)
20992175 return NULL ;
21002176 }
21012177 PyInterpreterState * interp = _PyInterpreterState_GET ();
2178+
2179+ if (interp -> monitoring_tool_names [tool_id ] != NULL ) {
2180+ if (_PyMonitoring_ClearToolId (tool_id ) < 0 ) {
2181+ return NULL ;
2182+ }
2183+ }
2184+
21022185 Py_CLEAR (interp -> monitoring_tool_names [tool_id ]);
21032186 Py_RETURN_NONE ;
21042187}
@@ -2376,6 +2459,7 @@ monitoring__all_events_impl(PyObject *module)
23762459
23772460static PyMethodDef methods [] = {
23782461 MONITORING_USE_TOOL_ID_METHODDEF
2462+ MONITORING_CLEAR_TOOL_ID_METHODDEF
23792463 MONITORING_FREE_TOOL_ID_METHODDEF
23802464 MONITORING_GET_TOOL_METHODDEF
23812465 MONITORING_REGISTER_CALLBACK_METHODDEF
0 commit comments