https://github.com/python/cpython/commit/18e0bcb85f9a93c0a500b4388cb5fabc59869569
commit: 18e0bcb85f9a93c0a500b4388cb5fabc59869569
branch: 3.15
author: Victor Stinner <[email protected]>
committer: vstinner <[email protected]>
date: 2026-10-12T23:32:24Z
summary:

[3.15] gh-157415: Fix data race in pthread wrapper (#157430) (#159277)

gh-157415: Fix data race in pthread wrapper (#157430)

Use free() instead of PyMem_RawFree() in pythread_wrapper() to avoid
a data race if another thread calls PyMem_SetAllocator() in parallel.

Reenable @nomemtest tests on TSAN.


(cherry picked from commit d1878ccb44999bfa30f5a0e84b4383e6068e5b72)

Co-authored-by: Nathan Goldbaum <[email protected]>

files:
M Lib/test/support/__init__.py
M Python/thread_pthread.h

diff --git a/Lib/test/support/__init__.py b/Lib/test/support/__init__.py
index 5a142ac4adca56..ef04637a49197b 100644
--- a/Lib/test/support/__init__.py
+++ b/Lib/test/support/__init__.py
@@ -1314,12 +1314,7 @@ def internal(*args, **kwargs):
         import_module('_testcapi')
         return f(*args, **kwargs)
 
-    return unittest.skipIf(
-        # Python built with Py_TRACE_REFS fail with a fatal error in
-        # _PyRefchain_Trace() on memory allocation error.
-        Py_TRACE_REFS,
-        'cannot test Py_TRACE_REFS build',
-    )(cpython_only(internal))
+    return cpython_only(internal)
 
 def bigaddrspacetest(f):
     """Decorator for tests that fill the address space."""
diff --git a/Python/thread_pthread.h b/Python/thread_pthread.h
index de93178576e6ec..4972a2a6b36c9b 100644
--- a/Python/thread_pthread.h
+++ b/Python/thread_pthread.h
@@ -229,7 +229,7 @@ pythread_wrapper(void *arg)
     pythread_callback *callback = arg;
     void (*func)(void *) = callback->func;
     void *func_arg = callback->arg;
-    PyMem_RawFree(arg);
+    free(callback);
 
     func(func_arg);
     return NULL;
@@ -269,7 +269,9 @@ do_start_joinable_thread(void (*func)(void *), void *arg, 
pthread_t* out_id)
     pthread_attr_setscope(&attrs, PTHREAD_SCOPE_SYSTEM);
 #endif
 
-    pythread_callback *callback = PyMem_RawMalloc(sizeof(pythread_callback));
+    // Use free() instead of PyMem_RawFree() in pythread_wrapper() to avoid a
+    // data race if another thread calls PyMem_SetAllocator() in parallel.
+    pythread_callback *callback = malloc(sizeof(pythread_callback));
 
     if (callback == NULL) {
       return -1;
@@ -291,7 +293,7 @@ do_start_joinable_thread(void (*func)(void *), void *arg, 
pthread_t* out_id)
 #endif
 
     if (status != 0) {
-        PyMem_RawFree(callback);
+        free(callback);
         return -1;
     }
     *out_id = th;

_______________________________________________
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