https://github.com/python/cpython/commit/9a6b60af409d02468b935c569a4f49e88c399c4e
commit: 9a6b60af409d02468b935c569a4f49e88c399c4e
branch: main
author: Kumar Aditya <kumaradi...@python.org>
committer: kumaraditya303 <kumaradi...@python.org>
date: 2025-07-24T17:58:46Z
summary:

gh-136870: fix data races in instrumentation of bytecode (#136994)

De-instrumenting code objects modifies the thread local bytecode for all 
threads as such, holding the critical section on the code object is not 
sufficient and leads to data races. Now, the de-instrumentation is now 
performed under a stop the world pause as such no thread races with executing 
the thread local bytecode while it is being de-instrumented.

files:
A 
Misc/NEWS.d/next/Core_and_Builtins/2025-07-24-17-30-58.gh-issue-136870.ncx82J.rst
M Python/instrumentation.c

diff --git 
a/Misc/NEWS.d/next/Core_and_Builtins/2025-07-24-17-30-58.gh-issue-136870.ncx82J.rst
 
b/Misc/NEWS.d/next/Core_and_Builtins/2025-07-24-17-30-58.gh-issue-136870.ncx82J.rst
new file mode 100644
index 00000000000000..7552dc69169b67
--- /dev/null
+++ 
b/Misc/NEWS.d/next/Core_and_Builtins/2025-07-24-17-30-58.gh-issue-136870.ncx82J.rst
@@ -0,0 +1 @@
+Fix data races while de-instrumenting bytecode of code objects running 
concurrently in threads.
diff --git a/Python/instrumentation.c b/Python/instrumentation.c
index 44de480cd2304a..f9913cff402ed1 100644
--- a/Python/instrumentation.c
+++ b/Python/instrumentation.c
@@ -1190,9 +1190,10 @@ call_instrumentation_vector(
                 break;
             }
             else {
-                LOCK_CODE(code);
+                PyInterpreterState *interp = tstate->interp;
+                _PyEval_StopTheWorld(interp);
                 remove_tools(code, offset, event, 1 << tool);
-                UNLOCK_CODE();
+                _PyEval_StartTheWorld(interp);
             }
         }
     }
@@ -1381,9 +1382,10 @@ _Py_call_instrumentation_line(PyThreadState *tstate, 
_PyInterpreterFrame* frame,
         }
         else {
             /* DISABLE  */
-            LOCK_CODE(code);
+            PyInterpreterState *interp = tstate->interp;
+            _PyEval_StopTheWorld(interp);
             remove_line_tools(code, i, 1 << tool);
-            UNLOCK_CODE();
+            _PyEval_StartTheWorld(interp);
         }
     } while (tools);
     Py_DECREF(line_obj);
@@ -1438,9 +1440,10 @@ _Py_call_instrumentation_instruction(PyThreadState 
*tstate, _PyInterpreterFrame*
         }
         else {
             /* DISABLE  */
-            LOCK_CODE(code);
+            PyInterpreterState *interp = tstate->interp;
+            _PyEval_StopTheWorld(interp);
             remove_per_instruction_tools(code, offset, 1 << tool);
-            UNLOCK_CODE();
+            _PyEval_StartTheWorld(interp);
         }
     }
     Py_DECREF(offset_obj);
@@ -2995,9 +2998,10 @@ branch_handler_vectorcall(
             // Orphaned NOT_TAKEN -- Jump removed by the compiler
             return res;
         }
-        LOCK_CODE(code);
+        PyInterpreterState *interp = _PyInterpreterState_GET();
+        _PyEval_StopTheWorld(interp);
         remove_tools(code, offset, other_event, 1 << self->tool_id);
-        UNLOCK_CODE();
+        _PyEval_StartTheWorld(interp);
     }
     return res;
 }

_______________________________________________
Python-checkins mailing list -- python-checkins@python.org
To unsubscribe send an email to python-checkins-le...@python.org
https://mail.python.org/mailman3//lists/python-checkins.python.org
Member address: arch...@mail-archive.com

Reply via email to