From 40bf9a89eb1a66dfa4ab9f97ec418e2e6878dc67 Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Wed, 24 Nov 2021 19:34:57 -0500 Subject: [PATCH] thread: initialize uv_thread_self for all threads (#3357) In particular, previously the main thread would have an id of NULL, which was then not valid to use with any other API that expected a uv_thread_t handle. --- src/win/thread.c | 15 +++++++++++++-- test/test-thread-equal.c | 6 ++++++ 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/src/win/thread.c b/src/win/thread.c index 89c53ada7..3615101b4 100644 --- a/src/win/thread.c +++ b/src/win/thread.c @@ -103,7 +103,7 @@ static UINT __stdcall uv__thread_start(void* arg) { uv__free(ctx_p); uv_once(&uv__current_thread_init_guard, uv__init_current_thread_key); - uv_key_set(&uv__current_thread_key, (void*) ctx.self); + uv_key_set(&uv__current_thread_key, ctx.self); ctx.entry(ctx.arg); @@ -183,7 +183,18 @@ int uv_thread_create_ex(uv_thread_t* tid, uv_thread_t uv_thread_self(void) { uv_once(&uv__current_thread_init_guard, uv__init_current_thread_key); - return (uv_thread_t) uv_key_get(&uv__current_thread_key); + uv_thread_t key = uv_key_get(&uv__current_thread_key); + if (key == NULL) { + /* If the thread wasn't started by uv_thread_create (such as the main + * thread), we assign an id to it now. */ + if (!DuplicateHandle(GetCurrentProcess(), GetCurrentThread(), + GetCurrentProcess(), &key, 0, + FALSE, DUPLICATE_SAME_ACCESS)) { + uv_fatal_error(GetLastError(), "DuplicateHandle"); + } + uv_key_set(&uv__current_thread_key, key); + } + return key; } diff --git a/test/test-thread-equal.c b/test/test-thread-equal.c index 27c07ee2c..f7bde71b3 100644 --- a/test/test-thread-equal.c +++ b/test/test-thread-equal.c @@ -28,6 +28,9 @@ uv_thread_t subthreads[2]; static void check_thread(void* arg) { uv_thread_t *thread_id = arg; uv_thread_t self_id = uv_thread_self(); +#ifdef _WIN32 + ASSERT_NOT_NULL(self_id); +#endif ASSERT(uv_thread_equal(&main_thread_id, &self_id) == 0); *thread_id = uv_thread_self(); } @@ -35,6 +38,9 @@ static void check_thread(void* arg) { TEST_IMPL(thread_equal) { uv_thread_t threads[2]; main_thread_id = uv_thread_self(); +#ifdef _WIN32 + ASSERT_NOT_NULL(main_thread_id); +#endif ASSERT(0 != uv_thread_equal(&main_thread_id, &main_thread_id)); ASSERT(0 == uv_thread_create(threads + 0, check_thread, subthreads + 0)); ASSERT(0 == uv_thread_create(threads + 1, check_thread, subthreads + 1));