From 4240cfb999f29b00414c0ba659742f37b23589c0 Mon Sep 17 00:00:00 2001 From: Ivan Maidanski Date: Mon, 19 Dec 2022 10:01:18 +0300 Subject: Disallow explicit unregister of non-main thread if registered by DllMain This is to match the behavior on non-Windows platforms (and to match the comment of GC_delete_thread). * include/private/pthread_support.h [GC_WIN32_THREADS && !GC_NO_THREADS_DISCOVERY && GC_ASSERTIONS] (GC_main_thread_id): Declare variable. * include/private/pthread_support.h [GC_WIN32_THREADS && !GC_NO_THREADS_DISCOVERY] (GC_delete_thread): Remove. * pthread_support.c (GC_delete_thread): Change GC_INNER_WIN32THREAD to STATIC. * pthread_support.c [!GC_NO_THREADS_DISCOVERY && GC_WIN32_THREADS] (GC_delete_thread): Call GC_win32_dll_lookup_thread instead of GC_lookup_thread and do not check its result. * pthread_support.c [!GC_NO_THREADS_DISCOVERY && GC_WIN32_THREADS] (GC_unregister_my_thread): Do not call GC_delete_thread (directly) if GC_win32_dll_threads; add assertion to check that the thread to b unregistered is main one if GC_win32_dll_threads; add comment. * win32_threads.c [!GC_NO_THREADS_DISCOVERY] (main_thread_id): Rename to GC_main_thread_id and change static to GC_INNER to STATIC. * win32_threads.c (GC_register_my_thread_inner): Update comment to mention GC_win32_dll_lookup_thread instead of GC_delete_thread. * win32_threads.c (GC_thr_init): Define self_id local variable and use it instead of main_thread_id; do not define main_thread_id as macro; do not undefine main_thread_id. * win32_threads.c [!GC_NO_THREADS_DISCOVERY] (GC_DllMain): Call GC_win32_dll_lookup_thread() and GC_delete_gc_thread_no_free() instead of GC_delete_thread() (w/o a warning if the thread is not found). --- pthread_support.c | 31 ++++++++++--------------------- 1 file changed, 10 insertions(+), 21 deletions(-) (limited to 'pthread_support.c') diff --git a/pthread_support.c b/pthread_support.c index 08d52375..808ec458 100644 --- a/pthread_support.c +++ b/pthread_support.c @@ -743,17 +743,13 @@ GC_INNER_WIN32THREAD GC_thread GC_new_thread(thread_id_t id) /* If GC_win32_dll_threads is set then it should be called from */ /* the thread being deleted. It is also safe to delete the */ /* main thread (unless GC_win32_dll_threads). */ -GC_INNER_WIN32THREAD void GC_delete_thread(thread_id_t id) +STATIC void GC_delete_thread(thread_id_t id) { # if !defined(GC_NO_THREADS_DISCOVERY) && defined(GC_WIN32_THREADS) if (GC_win32_dll_threads) { - GC_thread t = GC_lookup_thread(id); + GC_thread t = GC_win32_dll_lookup_thread(id); - if (EXPECT(NULL == t, FALSE)) { - WARN("Removing nonexistent thread, id= %" WARN_PRIuPTR "\n", id); - } else { - GC_delete_gc_thread_no_free(t); - } + GC_delete_gc_thread_no_free(t); } else # endif /* else */ { @@ -2146,23 +2142,17 @@ STATIC void GC_unregister_my_thread_inner(GC_thread me) GC_API int GC_CALL GC_unregister_my_thread(void) { -# if !defined(GC_NO_THREADS_DISCOVERY) && defined(GC_WIN32_THREADS) - if (GC_win32_dll_threads) { -# ifdef THREAD_LOCAL_ALLOC - /* Can't happen: see GC_use_threads_discovery(). */ - GC_ASSERT(FALSE); -# else - /* FIXME: Should we just ignore this? */ - GC_delete_thread(thread_id_self()); -# endif - } else -# endif - /* else */ { thread_id_t self_id = thread_id_self(); GC_thread me; IF_CANCEL(int cancel_state;) DCL_LOCK_STATE; + /* Client should not unregister the thread explicitly if it */ + /* is registered by DllMain, except for the main thread. */ +# if !defined(GC_NO_THREADS_DISCOVERY) && defined(GC_WIN32_THREADS) + GC_ASSERT(!GC_win32_dll_threads || GC_main_thread_id == self_id); +# endif + LOCK(); DISABLE_CANCEL(cancel_state); /* Wait for any GC that may be marking from our stack to */ @@ -2178,8 +2168,7 @@ GC_API int GC_CALL GC_unregister_my_thread(void) GC_unregister_my_thread_inner(me); RESTORE_CANCEL(cancel_state); UNLOCK(); - } - return GC_SUCCESS; + return GC_SUCCESS; } #if !defined(GC_NO_PTHREAD_CANCEL) && defined(GC_PTHREADS) -- cgit v1.2.1