mirror of
https://github.com/python/cpython.git
synced 2026-01-06 07:22:09 +00:00
gh-128421: Avoid TSAN warnings in sys._current_frames() (gh-131548)
This tells TSAN not to sanitize `PyUnstable_InterpreterFrame_GetLine()`. There's a possible data race on the access to the frame's `instr_ptr` if the frame is currently executing. We don't really care about the race. In theory, we could use relaxed atomics for every access to `instr_ptr`, but that would create more code churn and current compilers are overly conservative with optimizations around relaxed atomic accesses. We also don't sanitize `_PyFrame_IsIncomplete()` because it accesses `instr_ptr` and is called from assertions within PyFrame_GetCode().
This commit is contained in:
parent
4596666a9f
commit
da6730caa5
4 changed files with 25 additions and 36 deletions
|
|
@ -189,8 +189,11 @@ _PyFrame_SetStackPointer(_PyInterpreterFrame *frame, _PyStackRef *stack_pointer)
|
|||
* Frames on the frame stack are incomplete until the
|
||||
* first RESUME instruction.
|
||||
* Frames owned by a generator are always complete.
|
||||
*
|
||||
* NOTE: We allow racy accesses to the instruction pointer
|
||||
* from other threads for sys._current_frames() and similar APIs.
|
||||
*/
|
||||
static inline bool
|
||||
static inline bool _Py_NO_SANITIZE_THREAD
|
||||
_PyFrame_IsIncomplete(_PyInterpreterFrame *frame)
|
||||
{
|
||||
if (frame->owner >= FRAME_OWNED_BY_INTERPRETER) {
|
||||
|
|
|
|||
|
|
@ -565,27 +565,45 @@ extern "C" {
|
|||
# if __has_feature(memory_sanitizer)
|
||||
# if !defined(_Py_MEMORY_SANITIZER)
|
||||
# define _Py_MEMORY_SANITIZER
|
||||
# define _Py_NO_SANITIZE_MEMORY __attribute__((no_sanitize_memory))
|
||||
# endif
|
||||
# endif
|
||||
# if __has_feature(address_sanitizer)
|
||||
# if !defined(_Py_ADDRESS_SANITIZER)
|
||||
# define _Py_ADDRESS_SANITIZER
|
||||
# define _Py_NO_SANITIZE_ADDRESS __attribute__((no_sanitize_address))
|
||||
# endif
|
||||
# endif
|
||||
# if __has_feature(thread_sanitizer)
|
||||
# if !defined(_Py_THREAD_SANITIZER)
|
||||
# define _Py_THREAD_SANITIZER
|
||||
# define _Py_NO_SANITIZE_THREAD __attribute__((no_sanitize_thread))
|
||||
# endif
|
||||
# endif
|
||||
#elif defined(__GNUC__)
|
||||
# if defined(__SANITIZE_ADDRESS__)
|
||||
# define _Py_ADDRESS_SANITIZER
|
||||
# define _Py_NO_SANITIZE_ADDRESS __attribute__((no_sanitize_address))
|
||||
# endif
|
||||
# if defined(__SANITIZE_THREAD__)
|
||||
# define _Py_THREAD_SANITIZER
|
||||
# define _Py_NO_SANITIZE_THREAD __attribute__((no_sanitize_thread))
|
||||
# elif __GNUC__ > 5 || (__GNUC__ == 5 && __GNUC_MINOR__ >= 1)
|
||||
// TSAN is supported since GCC 5.1, but __SANITIZE_THREAD__ macro
|
||||
// is provided only since GCC 7.
|
||||
# define _Py_NO_SANITIZE_THREAD __attribute__((no_sanitize_thread))
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifndef _Py_NO_SANITIZE_ADDRESS
|
||||
# define _Py_NO_SANITIZE_ADDRESS
|
||||
#endif
|
||||
#ifndef _Py_NO_SANITIZE_THREAD
|
||||
# define _Py_NO_SANITIZE_THREAD
|
||||
#endif
|
||||
#ifndef _Py_NO_SANITIZE_MEMORY
|
||||
# define _Py_NO_SANITIZE_MEMORY
|
||||
#endif
|
||||
|
||||
/* AIX has __bool__ redefined in it's system header file. */
|
||||
#if defined(_AIX) && defined(__bool__)
|
||||
|
|
|
|||
|
|
@ -470,40 +470,6 @@ _PyMem_ArenaFree(void *Py_UNUSED(ctx), void *ptr,
|
|||
/*******************************************/
|
||||
|
||||
|
||||
#if defined(__has_feature) /* Clang */
|
||||
# if __has_feature(address_sanitizer) /* is ASAN enabled? */
|
||||
# define _Py_NO_SANITIZE_ADDRESS \
|
||||
__attribute__((no_sanitize("address")))
|
||||
# endif
|
||||
# if __has_feature(thread_sanitizer) /* is TSAN enabled? */
|
||||
# define _Py_NO_SANITIZE_THREAD __attribute__((no_sanitize_thread))
|
||||
# endif
|
||||
# if __has_feature(memory_sanitizer) /* is MSAN enabled? */
|
||||
# define _Py_NO_SANITIZE_MEMORY __attribute__((no_sanitize_memory))
|
||||
# endif
|
||||
#elif defined(__GNUC__)
|
||||
# if defined(__SANITIZE_ADDRESS__) /* GCC 4.8+, is ASAN enabled? */
|
||||
# define _Py_NO_SANITIZE_ADDRESS \
|
||||
__attribute__((no_sanitize_address))
|
||||
# endif
|
||||
// TSAN is supported since GCC 5.1, but __SANITIZE_THREAD__ macro
|
||||
// is provided only since GCC 7.
|
||||
# if __GNUC__ > 5 || (__GNUC__ == 5 && __GNUC_MINOR__ >= 1)
|
||||
# define _Py_NO_SANITIZE_THREAD __attribute__((no_sanitize_thread))
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifndef _Py_NO_SANITIZE_ADDRESS
|
||||
# define _Py_NO_SANITIZE_ADDRESS
|
||||
#endif
|
||||
#ifndef _Py_NO_SANITIZE_THREAD
|
||||
# define _Py_NO_SANITIZE_THREAD
|
||||
#endif
|
||||
#ifndef _Py_NO_SANITIZE_MEMORY
|
||||
# define _Py_NO_SANITIZE_MEMORY
|
||||
#endif
|
||||
|
||||
|
||||
#define ALLOCATORS_MUTEX (_PyRuntime.allocators.mutex)
|
||||
#define _PyMem_Raw (_PyRuntime.allocators.standard.raw)
|
||||
#define _PyMem (_PyRuntime.allocators.standard.mem)
|
||||
|
|
|
|||
|
|
@ -139,7 +139,9 @@ PyUnstable_InterpreterFrame_GetLasti(struct _PyInterpreterFrame *frame)
|
|||
return _PyInterpreterFrame_LASTI(frame) * sizeof(_Py_CODEUNIT);
|
||||
}
|
||||
|
||||
int
|
||||
// NOTE: We allow racy accesses to the instruction pointer from other threads
|
||||
// for sys._current_frames() and similar APIs.
|
||||
int _Py_NO_SANITIZE_THREAD
|
||||
PyUnstable_InterpreterFrame_GetLine(_PyInterpreterFrame *frame)
|
||||
{
|
||||
int addr = _PyInterpreterFrame_LASTI(frame) * sizeof(_Py_CODEUNIT);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue