Skip to content

Commit 51d6579

Browse files
committed
Return the main thread's short identifier on certain platforms
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 <[email protected]>
1 parent d63af95 commit 51d6579

File tree

1 file changed

+7
-0
lines changed

1 file changed

+7
-0
lines changed

Modules/_threadmodule.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2029,6 +2029,13 @@ An obsolete synonym of allocate_lock().");
20292029
static PyObject *
20302030
thread_get_ident(PyObject *self, PyObject *Py_UNUSED(ignored))
20312031
{
2032+
/* Work around an issue with the main thread ID to failing comparison checks
2033+
due to sign extension on some Linux libc implemenations. Can be removed
2034+
when thread identifiers are reworked. */
2035+
#if SIZEOF_LONG < SIZEOF_LONG_LONG && defined(__linux__) && !defined(__GLIBC__)
2036+
if (_Py_IsMainThread())
2037+
return PyLong_FromUnsignedLong(_PyRuntime.main_thread);
2038+
#endif
20322039
PyThread_ident_t ident = PyThread_get_thread_ident_ex();
20332040
if (ident == PYTHREAD_INVALID_THREAD_ID) {
20342041
PyErr_SetString(ThreadError, "no current thread ident");

0 commit comments

Comments
 (0)