123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100 |
- From 8a8f8d72212d043469ef33549e8edc3bce244516 Mon Sep 17 00:00:00 2001
- From: Vincent Fazio <vfazio@gmail.com>
- Date: Sat, 22 Feb 2025 19:43:26 -0600
- Subject: [PATCH] Fix thread identifiers on 32-bit musl builds
- 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'
- Fix this by compiling in code targeting non-glibc based Linux platforms
- to cast the pthread_t to a uintptr and then to PyThread_ident_t.
- Upstream: https://github.com/python/cpython/pull/130391
- [0]: https://gcc.gnu.org/onlinedocs/gcc-14.2.0/gcc/Arrays-and-pointers-implementation.html
- Signed-off-by: Vincent Fazio <vfazio@gmail.com>
- ---
- Python/thread_pthread.h | 31 ++++++++++++++++++++++---------
- 1 file changed, 22 insertions(+), 9 deletions(-)
- diff --git a/Python/thread_pthread.h b/Python/thread_pthread.h
- index f588b4620da..84900c86401 100644
- --- a/Python/thread_pthread.h
- +++ b/Python/thread_pthread.h
- @@ -307,6 +307,25 @@ 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) {
- +#if SIZEOF_PTHREAD_T > SIZEOF_LONG
- + return (PyThread_ident_t) *(unsigned long *) &value;
- +#else
- + PyThread_ident_t ident;
- +#if defined(__linux__) && !defined(__GLIBC__)
- + ident = (PyThread_ident_t) (uintptr_t) value;
- + assert(pthread_equal(value, (pthread_t) (uintptr_t) ident));
- +#else
- + ident = (PyThread_ident_t) value;
- + assert(pthread_equal(value, (pthread_t) ident));
- +#endif
- + return ident;
- +#endif // SIZEOF_PTHREAD_T > SIZEOF_LONG
- +}
- +
- int
- PyThread_start_joinable_thread(void (*func)(void *), void *arg,
- PyThread_ident_t* ident, PyThread_handle_t* handle) {
- @@ -314,9 +333,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;
- }
- @@ -329,11 +347,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
- @@ -358,8 +372,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
- --
- 2.34.1
|