summaryrefslogtreecommitdiff
path: root/win32_threads.c
diff options
context:
space:
mode:
authorIvan Maidanski <ivmai@mail.ru>2023-04-04 09:21:28 +0300
committerIvan Maidanski <ivmai@mail.ru>2023-04-06 13:16:52 +0300
commit68d419a51fa73765ac66beb348a6c577ca1963ac (patch)
tree67402be765bbb6006354696b70ad4a6c7d21b708 /win32_threads.c
parent5f16c0ab09760910e8995317ebc51b4fae198101 (diff)
downloadbdwgc-68d419a51fa73765ac66beb348a6c577ca1963ac.tar.gz
Fix signals delivery fail in find-leak mode if init from non-main thread
Issue #542 (bdwgc). The scenario of the failure (on Linux): - Find-leak mode is on - pthread_create/join primitives are not redirected - GC is initialized from a thread other than primordial - that thread is terminated (but not unregistered as the 1st one in GC) - the primordial thread exits and launches GC_exit_check - GC_gcollect tries to suspend the terminated thread by sending a signal - the signal is not delivered but pthread_kill just returns zero - the signal sending is retried until aborting with the proper message. The proposed solution (workaround) is not to call GC_gcollect at the process exit (in the find-leak mode) if GC_init was called from a thread other than primordial one. Check in GC_exit_check() (which is called if GC_find_leak) that the thread executing at-exit functions is the same as the one performed the GC initialization, otherwise the latter thread might already be dead but still registered and this, as a consequence, might cause a signal delivery fail when suspending the threads on platforms that do not guarantee ESRCH returned if the signal is not delivered (as observed on Ubuntu 22). * include/private/gc_priv.h [THREADS && !DONT_USE_ATEXIT] (GC_is_main_thread): Declare GC_INNER function. * include/private/pthread_support.h [GC_WIN32_THREADS && !DONT_USE_ATEXIT] (GC_main_thread_id): Declare variable. * include/private/pthread_support.h [GC_WIN32_THREADS && !GC_NO_THREADS_DISCOVERY] (GC_main_thread_id): Do not depend on GC_ASSERTIONS. * misc.c [!DONT_USE_ATEXIT && THREADS] (GC_exit_check): If not GC_is_main_thread() or not GC_thread_is_registered() then do not call GC_gcollect(); add comment; do not set and clear GC_in_thread_creation. * pthread_support.c [!GC_NO_THREADS_DISCOVERY && GC_WIN32_THREADS || !DONT_USE_ATEXIT] (GC_main_thread_id): Define variable. * pthread_support.c [!DONT_USE_ATEXIT] (GC_is_main_thread): Implement. * pthread_support.c [!GC_WIN32_THREADS] (GC_thr_init): Define self_id local variable. * pthread_support.c [!GC_WIN32_THREADS && !DONT_USE_ATEXIT] (GC_thr_init): Set GC_main_thread_id. * win32_threads.c [!DONT_USE_ATEXIT] (GC_thr_init): Likewise. * win32_threads.c [!GC_NO_THREADS_DISCOVERY] (GC_main_thread_id): Do not define variable.
Diffstat (limited to 'win32_threads.c')
-rw-r--r--win32_threads.c9
1 files changed, 1 insertions, 8 deletions
diff --git a/win32_threads.c b/win32_threads.c
index 91a2a037..d7cbf89b 100644
--- a/win32_threads.c
+++ b/win32_threads.c
@@ -109,13 +109,6 @@ GC_API void GC_CALL GC_use_threads_discovery(void)
}
#ifndef GC_NO_THREADS_DISCOVERY
-# ifdef GC_ASSERTIONS
- GC_INNER
-# else
- STATIC
-# endif
- thread_id_t GC_main_thread_id;
-
/* We track thread attachments while the world is supposed to be */
/* stopped. Unfortunately, we cannot stop them from starting, since */
/* blocking in DllMain seems to cause the world to deadlock. Thus, */
@@ -1642,7 +1635,7 @@ GC_INNER void GC_thr_init(void)
# ifdef GC_ASSERTIONS
GC_thr_initialized = TRUE;
# endif
-# ifndef GC_NO_THREADS_DISCOVERY
+# if !defined(DONT_USE_ATEXIT) || !defined(GC_NO_THREADS_DISCOVERY)
GC_main_thread_id = self_id;
# endif
# ifdef CAN_HANDLE_FORK