]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
gh-143108: Don't instrument faulthandler.c for TSan (#143109)
authorSam Gross <colesbury@gmail.com>
Wed, 24 Dec 2025 01:12:55 +0000 (20:12 -0500)
committerGitHub <noreply@github.com>
Wed, 24 Dec 2025 01:12:55 +0000 (02:12 +0100)
The dumping of tracebacks has data races and that's okay (it's best
effort).

Include/internal/pycore_interpframe.h
Python/traceback.c
Tools/tsan/suppressions_free_threading.txt

index 8949d6cc2fc4bb3963ede55323958cd039d6f371..2e9fbd39b276b16ca005279346b98fc7b085c265 100644 (file)
@@ -27,7 +27,7 @@ static inline PyCodeObject *_PyFrame_GetCode(_PyInterpreterFrame *f) {
 // Similar to _PyFrame_GetCode(), but return NULL if the frame is invalid or
 // freed. Used by dump_frame() in Python/traceback.c. The function uses
 // heuristics to detect freed memory, it's not 100% reliable.
-static inline PyCodeObject*
+static inline PyCodeObject* _Py_NO_SANITIZE_THREAD
 _PyFrame_SafeGetCode(_PyInterpreterFrame *f)
 {
     // globals and builtins may be NULL on a legit frame, but it's unlikely.
@@ -70,7 +70,7 @@ _PyFrame_GetBytecode(_PyInterpreterFrame *f)
 // Similar to PyUnstable_InterpreterFrame_GetLasti(), but return NULL if the
 // frame is invalid or freed. Used by dump_frame() in Python/traceback.c. The
 // function uses heuristics to detect freed memory, it's not 100% reliable.
-static inline int
+static inline int _Py_NO_SANITIZE_THREAD
 _PyFrame_SafeGetLasti(struct _PyInterpreterFrame *f)
 {
     // Code based on _PyFrame_GetBytecode() but replace _PyFrame_GetCode()
index 264f034dea7fa5bddd7582145de297fdc3cfc4b6..40e19c7cc82075d1f79cfe81ff91459d5f81763f 100644 (file)
@@ -1035,7 +1035,7 @@ _Py_DumpWideString(int fd, wchar_t *str)
 
    Return 0 on success. Return -1 if the frame is invalid. */
 
-static int
+static int _Py_NO_SANITIZE_THREAD
 dump_frame(int fd, _PyInterpreterFrame *frame)
 {
     if (frame->owner == FRAME_OWNED_BY_INTERPRETER) {
@@ -1088,7 +1088,7 @@ dump_frame(int fd, _PyInterpreterFrame *frame)
     return res;
 }
 
-static int
+static int _Py_NO_SANITIZE_THREAD
 tstate_is_freed(PyThreadState *tstate)
 {
     if (_PyMem_IsPtrFreed(tstate)) {
@@ -1104,14 +1104,14 @@ tstate_is_freed(PyThreadState *tstate)
 }
 
 
-static int
+static int _Py_NO_SANITIZE_THREAD
 interp_is_freed(PyInterpreterState *interp)
 {
     return _PyMem_IsPtrFreed(interp);
 }
 
 
-static void
+static void _Py_NO_SANITIZE_THREAD
 dump_traceback(int fd, PyThreadState *tstate, int write_header)
 {
     if (write_header) {
@@ -1263,7 +1263,7 @@ write_thread_id(int fd, PyThreadState *tstate, int is_current)
 
    The caller is responsible to call PyErr_CheckSignals() to call Python signal
    handlers if signals were received. */
-const char*
+const char* _Py_NO_SANITIZE_THREAD
 _Py_DumpTracebackThreads(int fd, PyInterpreterState *interp,
                          PyThreadState *current_tstate)
 {
@@ -1332,7 +1332,7 @@ _Py_DumpTracebackThreads(int fd, PyInterpreterState *interp,
         }
         dump_traceback(fd, tstate, 0);
 
-        tstate = PyThreadState_Next(tstate);
+        tstate = tstate->next;
         nthreads++;
     } while (tstate != NULL);
     _Py_END_SUPPRESS_IPH
index e2cf6d58b0cfd993a97d91fb58936c60259834a2..f05e0ded9865f884ee36f9e9c748d6916a5ce8a7 100644 (file)
 
 # These warnings trigger directly in a CPython function.
 
-race_top:dump_traceback
-race_top:fatal_error
-race_top:_PyFrame_GetCode
-race_top:_PyFrame_Initialize
 race_top:_PyObject_TryGetInstanceAttribute
-race_top:PyUnstable_InterpreterFrame_GetLine
-race_top:write_thread_id
 
 # https://gist.github.com/mpage/6962e8870606cfc960e159b407a0cb40
 thread:pthread_create