https://github.com/python/cpython/commit/4f5a67a32c5cd5016211834d0fa8eaca1c9f9d6b
commit: 4f5a67a32c5cd5016211834d0fa8eaca1c9f9d6b
branch: main
author: Shardul Deshpande <[email protected]>
committer: kumaraditya303 <[email protected]>
date: 2026-10-22T14:59:30+05:30
summary:

gh-157194: Read the opcode atomically in the specializer (#157195)

files:
A 
Misc/NEWS.d/next/Core_and_Builtins/2026-09-08-17-40-00.gh-issue-157194.17Ffhk.rst
M Python/specialize.c

diff --git 
a/Misc/NEWS.d/next/Core_and_Builtins/2026-09-08-17-40-00.gh-issue-157194.17Ffhk.rst
 
b/Misc/NEWS.d/next/Core_and_Builtins/2026-09-08-17-40-00.gh-issue-157194.17Ffhk.rst
new file mode 100644
index 00000000000000..c9817f876cd79f
--- /dev/null
+++ 
b/Misc/NEWS.d/next/Core_and_Builtins/2026-09-08-17-40-00.gh-issue-157194.17Ffhk.rst
@@ -0,0 +1,4 @@
+Fix a data race in the free-threaded build, reported by ThreadSanitizer,
+between the specializer reading an instruction opcode and another thread
+writing it. Only reachable when thread-local bytecode is disabled with
+``-X tlbc=0``, which makes threads share one copy of the bytecode.
diff --git a/Python/specialize.c b/Python/specialize.c
index f658df3bc5d222..fc5aef67301f2a 100644
--- a/Python/specialize.c
+++ b/Python/specialize.c
@@ -2345,7 +2345,7 @@ _Py_Specialize_BinaryOp(_PyStackRef lhs_st, _PyStackRef 
rhs_st, _Py_CODEUNIT *in
     assert(_PyOpcode_Caches[BINARY_OP] == INLINE_CACHE_ENTRIES_BINARY_OP);
 
     _PyBinaryOpCache *cache = (_PyBinaryOpCache *)(instr + 1);
-    if (instr->op.code == BINARY_OP_EXTEND) {
+    if (FT_ATOMIC_LOAD_UINT8_RELAXED(instr->op.code) == BINARY_OP_EXTEND) {
         write_ptr(cache->external_cache, NULL);
     }
 
@@ -2951,7 +2951,8 @@ _Py_Specialize_GetIter(_PyStackRef iterable, _Py_CODEUNIT 
*instr)
 void
 _Py_Specialize_Resume(_Py_CODEUNIT *instr, PyThreadState *tstate, 
_PyInterpreterFrame *frame)
 {
-    if (tstate->tracing == 0 && instr->op.code == RESUME) {
+    if (tstate->tracing == 0 &&
+        FT_ATOMIC_LOAD_UINT8_RELAXED(instr->op.code) == RESUME) {
         if (tstate->interp->jit) {
             PyCodeObject *co = (PyCodeObject 
*)PyStackRef_AsPyObjectBorrow(frame->f_executable);
             if (co != NULL &&

_______________________________________________
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3//lists/python-checkins.python.org
Member address: [email protected]

Reply via email to