diff --git a/Misc/NEWS.d/next/Library/2021-01-21-18-03-09.bpo-42888.0oAR2x.rst b/Misc/NEWS.d/next/Library/2021-01-21-18-03-09.bpo-42888.0oAR2x.rst new file mode 100644 index 000000000000000..d77cafcb961ec05 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2021-01-21-18-03-09.bpo-42888.0oAR2x.rst @@ -0,0 +1,4 @@ +Remove calls of :c:func:`PyThread_exit_thread()` from top-level thread +functions, thereby avoiding a runtime dependency on ``libgcc_s.so`` and +associated issues with lazy-loading it via ``dlopen()`` in typical scenarios +on glibc-based Linux systems. diff --git a/Modules/_testcapimodule.c b/Modules/_testcapimodule.c index 4f97927fa232298..0b8d8b3cdc07c0e 100644 --- a/Modules/_testcapimodule.c +++ b/Modules/_testcapimodule.c @@ -4512,8 +4512,6 @@ temporary_c_thread(void *data) PyGILState_Release(state); PyThread_release_lock(test_c_thread->exit_event); - - PyThread_exit_thread(); } static PyObject * diff --git a/Modules/_threadmodule.c b/Modules/_threadmodule.c index 9b8757715a0b9b1..2e1fff3ad92e95e 100644 --- a/Modules/_threadmodule.c +++ b/Modules/_threadmodule.c @@ -1087,8 +1087,6 @@ thread_run(void *boot_raw) tstate->interp->num_threads--; PyThreadState_Clear(tstate); _PyThreadState_DeleteCurrent(tstate); - - PyThread_exit_thread(); } static PyObject * diff --git a/Programs/_testembed.c b/Programs/_testembed.c index 52c56746813a348..87a1da30982341f 100644 --- a/Programs/_testembed.c +++ b/Programs/_testembed.c @@ -241,8 +241,6 @@ static void bpo20891_thread(void *lockp) PyGILState_Release(state); PyThread_release_lock(lock); - - PyThread_exit_thread(); } static int test_bpo20891(void) diff --git a/Python/thread_nt.h b/Python/thread_nt.h index 05b982d32dc5260..6c7d93d75bf1fca 100644 --- a/Python/thread_nt.h +++ b/Python/thread_nt.h @@ -160,6 +160,13 @@ PyThread__init_thread(void) * Thread support. */ +static void +_pythread_at_thread_exit(void) +{ + dprintf(("%lu: _pythread_at_thread_exit called\n", + PyThread_get_thread_ident())); +} + typedef struct { void (*func)(void*); void *arg; @@ -175,6 +182,7 @@ bootstrap(void *call) void *arg = obj->arg; HeapFree(GetProcessHeap(), 0, obj); func(arg); + _pythread_at_thread_exit(); return 0; } @@ -254,7 +262,7 @@ PyThread_get_thread_native_id(void) void _Py_NO_RETURN PyThread_exit_thread(void) { - dprintf(("%lu: PyThread_exit_thread called\n", PyThread_get_thread_ident())); + _pythread_at_thread_exit(); if (!initialized) exit(0); _endthreadex(0); diff --git a/Python/thread_pthread.h b/Python/thread_pthread.h index ec7d737518b68c6..60bbe2b232d03b7 100644 --- a/Python/thread_pthread.h +++ b/Python/thread_pthread.h @@ -218,6 +218,12 @@ PyThread__init_thread(void) * Thread support. */ +static void +_pythread_at_thread_exit(void) +{ + dprintf(("_pythread_at_thread_exit called\n")); +} + /* bpo-33015: pythread_callback struct and pythread_wrapper() cast "void func(void *)" to "void* func(void *)": always return NULL. @@ -238,6 +244,7 @@ pythread_wrapper(void *arg) PyMem_RawFree(arg); func(func_arg); + _pythread_at_thread_exit(); return NULL; } @@ -359,7 +366,7 @@ PyThread_get_thread_native_id(void) void _Py_NO_RETURN PyThread_exit_thread(void) { - dprintf(("PyThread_exit_thread called\n")); + _pythread_at_thread_exit(); if (!initialized) exit(0); pthread_exit(0);