https://github.com/python/cpython/commit/72123063ddee84bb2c9d591a23f420997e35af5a commit: 72123063ddee84bb2c9d591a23f420997e35af5a branch: main author: Vincent Fazio <vfa...@gmail.com> committer: pitrou <pit...@free.fr> date: 2025-04-04T16:31:37+02:00 summary:
gh-130115: fix thread identifiers for 32-bit musl (#130391) CPython's pthread-based thread identifier relies on pthread_t being able to be represented as an unsigned integer type. This is true in most Linux libc implementations where it's defined as an unsigned long, however musl typedefs it as a struct *. If the pointer has the high bit set and is cast to PyThread_ident_t, the resultant value can be sign-extended [0]. This can cause issues when comparing against threading._MainThread's identifier. The main thread's identifier value is retrieved via _get_main_thread_ident which is backed by an unsigned long which truncates sign extended bits. >>> hex(threading.main_thread().ident) '0xb6f33f3c' >>> hex(threading.current_thread().ident) '0xffffffffb6f33f3c' Work around this by conditionally compiling in some code for non-glibc based Linux platforms that are at risk of sign-extension to return a PyLong based on the main thread's unsigned long thread identifier if the current thread is the main thread. [0]: https://gcc.gnu.org/onlinedocs/gcc-14.2.0/gcc/Arrays-and-pointers-implementation.html --------- Signed-off-by: Vincent Fazio <vfa...@gmail.com> files: A Misc/NEWS.d/next/Core_and_Builtins/2025-02-21-00-12-24.gh-issue-130115.mF-rP6.rst M Python/thread_pthread.h diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2025-02-21-00-12-24.gh-issue-130115.mF-rP6.rst b/Misc/NEWS.d/next/Core_and_Builtins/2025-02-21-00-12-24.gh-issue-130115.mF-rP6.rst new file mode 100644 index 00000000000000..124da33f8836f6 --- /dev/null +++ b/Misc/NEWS.d/next/Core_and_Builtins/2025-02-21-00-12-24.gh-issue-130115.mF-rP6.rst @@ -0,0 +1 @@ +Fix an issue with thread identifiers being sign-extended on some platforms. diff --git a/Python/thread_pthread.h b/Python/thread_pthread.h index c010b3a827757f..da4058242448f3 100644 --- a/Python/thread_pthread.h +++ b/Python/thread_pthread.h @@ -306,6 +306,24 @@ do_start_joinable_thread(void (*func)(void *), void *arg, pthread_t* out_id) return 0; } +/* Helper to convert pthread_t to PyThread_ident_t. POSIX allows pthread_t to be + non-arithmetic, e.g., musl typedefs it as a pointer. */ +static PyThread_ident_t +_pthread_t_to_ident(pthread_t value) { +// Cast through an integer type of the same size to avoid sign-extension. +#if SIZEOF_PTHREAD_T == SIZEOF_VOID_P + return (uintptr_t) value; +#elif SIZEOF_PTHREAD_T == SIZEOF_LONG + return (unsigned long) value; +#elif SIZEOF_PTHREAD_T == SIZEOF_INT + return (unsigned int) value; +#elif SIZEOF_PTHREAD_T == SIZEOF_LONG_LONG + return (unsigned long long) value; +#else +#error "Unsupported SIZEOF_PTHREAD_T value" +#endif +} + int PyThread_start_joinable_thread(void (*func)(void *), void *arg, PyThread_ident_t* ident, PyThread_handle_t* handle) { @@ -313,9 +331,8 @@ PyThread_start_joinable_thread(void (*func)(void *), void *arg, if (do_start_joinable_thread(func, arg, &th)) { return -1; } - *ident = (PyThread_ident_t) th; + *ident = _pthread_t_to_ident(th); *handle = (PyThread_handle_t) th; - assert(th == (pthread_t) *ident); assert(th == (pthread_t) *handle); return 0; } @@ -328,11 +345,7 @@ PyThread_start_new_thread(void (*func)(void *), void *arg) return PYTHREAD_INVALID_THREAD_ID; } pthread_detach(th); -#if SIZEOF_PTHREAD_T <= SIZEOF_LONG - return (unsigned long) th; -#else - return (unsigned long) *(unsigned long *) &th; -#endif + return (unsigned long) _pthread_t_to_ident(th);; } int @@ -357,8 +370,7 @@ PyThread_get_thread_ident_ex(void) { if (!initialized) PyThread_init_thread(); threadid = pthread_self(); - assert(threadid == (pthread_t) (PyThread_ident_t) threadid); - return (PyThread_ident_t) threadid; + return _pthread_t_to_ident(threadid); } unsigned long _______________________________________________ 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