diff --git a/Python/instrumentation.c b/Python/instrumentation.c index 0af2070b5cd983a..6f3b533b941a866 100644 --- a/Python/instrumentation.c +++ b/Python/instrumentation.c @@ -2166,6 +2166,10 @@ check_valid_tool(int tool_id) return 0; } +// Protects the interp->monitoring_tool_names array against concurrent +// use_tool_id/clear_tool_id/free_tool_id/get_tool calls. +static PyMutex monitoring_tool_names_mutex; + /*[clinic input] monitoring.use_tool_id @@ -2187,11 +2191,14 @@ monitoring_use_tool_id_impl(PyObject *module, int tool_id, PyObject *name) return NULL; } PyInterpreterState *interp = _PyInterpreterState_GET(); + PyMutex_Lock(&monitoring_tool_names_mutex); if (interp->monitoring_tool_names[tool_id] != NULL) { PyErr_Format(PyExc_ValueError, "tool %d is already in use", tool_id); + PyMutex_Unlock(&monitoring_tool_names_mutex); return NULL; } interp->monitoring_tool_names[tool_id] = Py_NewRef(name); + PyMutex_Unlock(&monitoring_tool_names_mutex); Py_RETURN_NONE; } @@ -2213,11 +2220,14 @@ monitoring_clear_tool_id_impl(PyObject *module, int tool_id) PyInterpreterState *interp = _PyInterpreterState_GET(); + PyMutex_Lock(&monitoring_tool_names_mutex); if (interp->monitoring_tool_names[tool_id] != NULL) { if (_PyMonitoring_ClearToolId(tool_id) < 0) { + PyMutex_Unlock(&monitoring_tool_names_mutex); return NULL; } } + PyMutex_Unlock(&monitoring_tool_names_mutex); Py_RETURN_NONE; } @@ -2239,13 +2249,16 @@ monitoring_free_tool_id_impl(PyObject *module, int tool_id) } PyInterpreterState *interp = _PyInterpreterState_GET(); + PyMutex_Lock(&monitoring_tool_names_mutex); if (interp->monitoring_tool_names[tool_id] != NULL) { if (_PyMonitoring_ClearToolId(tool_id) < 0) { + PyMutex_Unlock(&monitoring_tool_names_mutex); return NULL; } } Py_CLEAR(interp->monitoring_tool_names[tool_id]); + PyMutex_Unlock(&monitoring_tool_names_mutex); Py_RETURN_NONE; } @@ -2267,11 +2280,15 @@ monitoring_get_tool_impl(PyObject *module, int tool_id) return NULL; } PyInterpreterState *interp = _PyInterpreterState_GET(); + PyMutex_Lock(&monitoring_tool_names_mutex); PyObject *name = interp->monitoring_tool_names[tool_id]; if (name == NULL) { + PyMutex_Unlock(&monitoring_tool_names_mutex); Py_RETURN_NONE; } - return Py_NewRef(name); + PyObject *ret = Py_NewRef(name); + PyMutex_Unlock(&monitoring_tool_names_mutex); + return ret; } /*[clinic input]