0009-Fix-thread-identifiers-on-32-bit-musl-builds.patch 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100
  1. From 8a8f8d72212d043469ef33549e8edc3bce244516 Mon Sep 17 00:00:00 2001
  2. From: Vincent Fazio <vfazio@gmail.com>
  3. Date: Sat, 22 Feb 2025 19:43:26 -0600
  4. Subject: [PATCH] Fix thread identifiers on 32-bit musl builds
  5. CPython's pthread-based thread identifier relies on pthread_t being able
  6. to be represented as an unsigned integer type.
  7. This is true in most Linux libc implementations where it's defined as an
  8. unsigned long, however musl typedefs it as a struct *.
  9. If the pointer has the high bit set and is cast to PyThread_ident_t, the
  10. resultant value can be sign-extended [0]. This can cause issues when
  11. comparing against threading._MainThread's identifier. The main thread's
  12. identifier value is retrieved via _get_main_thread_ident which is backed
  13. by an unsigned long which truncates sign extended bits.
  14. >>> hex(threading.main_thread().ident)
  15. '0xb6f33f3c'
  16. >>> hex(threading.current_thread().ident)
  17. '0xffffffffb6f33f3c'
  18. Fix this by compiling in code targeting non-glibc based Linux platforms
  19. to cast the pthread_t to a uintptr and then to PyThread_ident_t.
  20. Upstream: https://github.com/python/cpython/pull/130391
  21. [0]: https://gcc.gnu.org/onlinedocs/gcc-14.2.0/gcc/Arrays-and-pointers-implementation.html
  22. Signed-off-by: Vincent Fazio <vfazio@gmail.com>
  23. ---
  24. Python/thread_pthread.h | 31 ++++++++++++++++++++++---------
  25. 1 file changed, 22 insertions(+), 9 deletions(-)
  26. diff --git a/Python/thread_pthread.h b/Python/thread_pthread.h
  27. index f588b4620da..84900c86401 100644
  28. --- a/Python/thread_pthread.h
  29. +++ b/Python/thread_pthread.h
  30. @@ -307,6 +307,25 @@ do_start_joinable_thread(void (*func)(void *), void *arg, pthread_t* out_id)
  31. return 0;
  32. }
  33. +/* Helper to convert pthread_t to PyThread_ident_t. POSIX allows pthread_t to be
  34. + non-arithmetic, e.g., musl typedefs it as a pointer */
  35. +static PyThread_ident_t
  36. +_pthread_t_to_ident(pthread_t value) {
  37. +#if SIZEOF_PTHREAD_T > SIZEOF_LONG
  38. + return (PyThread_ident_t) *(unsigned long *) &value;
  39. +#else
  40. + PyThread_ident_t ident;
  41. +#if defined(__linux__) && !defined(__GLIBC__)
  42. + ident = (PyThread_ident_t) (uintptr_t) value;
  43. + assert(pthread_equal(value, (pthread_t) (uintptr_t) ident));
  44. +#else
  45. + ident = (PyThread_ident_t) value;
  46. + assert(pthread_equal(value, (pthread_t) ident));
  47. +#endif
  48. + return ident;
  49. +#endif // SIZEOF_PTHREAD_T > SIZEOF_LONG
  50. +}
  51. +
  52. int
  53. PyThread_start_joinable_thread(void (*func)(void *), void *arg,
  54. PyThread_ident_t* ident, PyThread_handle_t* handle) {
  55. @@ -314,9 +333,8 @@ PyThread_start_joinable_thread(void (*func)(void *), void *arg,
  56. if (do_start_joinable_thread(func, arg, &th)) {
  57. return -1;
  58. }
  59. - *ident = (PyThread_ident_t) th;
  60. + *ident = _pthread_t_to_ident(th);
  61. *handle = (PyThread_handle_t) th;
  62. - assert(th == (pthread_t) *ident);
  63. assert(th == (pthread_t) *handle);
  64. return 0;
  65. }
  66. @@ -329,11 +347,7 @@ PyThread_start_new_thread(void (*func)(void *), void *arg)
  67. return PYTHREAD_INVALID_THREAD_ID;
  68. }
  69. pthread_detach(th);
  70. -#if SIZEOF_PTHREAD_T <= SIZEOF_LONG
  71. - return (unsigned long) th;
  72. -#else
  73. - return (unsigned long) *(unsigned long *) &th;
  74. -#endif
  75. + return (unsigned long) _pthread_t_to_ident(th);;
  76. }
  77. int
  78. @@ -358,8 +372,7 @@ PyThread_get_thread_ident_ex(void) {
  79. if (!initialized)
  80. PyThread_init_thread();
  81. threadid = pthread_self();
  82. - assert(threadid == (pthread_t) (PyThread_ident_t) threadid);
  83. - return (PyThread_ident_t) threadid;
  84. + return _pthread_t_to_ident(threadid);
  85. }
  86. unsigned long
  87. --
  88. 2.34.1