@samitouri / QOSamiQemu / commits / 71d81b320d

util: fix race setting thread name on Win32

The call to set the thread name on Win32 platforms is done by the parent thread, after _beginthreadex() returns. At this point the new child thread is potentially already executing its start method. To ensure the thread name is guaranteed to be set before any "interesting" code starts executing, it must be done in the start method of the child thread itself. Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Reviewed-by: Dr. David Alan Gilbert <dave@treblig.org> Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org> Reviewed-by: Markus Armbruster <armbru@redhat.com> Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>

Daniel P. Berrangé committed Feb 10, 2026 at 17:24 UTC 71d81b320dc0993306b71b2ff0f91b34cf219a38
1 file changed +10 -5
util/qemu-thread-win32.c
+10 -5
@@ -22,6 +22,8 @@ typedef HRESULT (WINAPI *pSetThreadDescription) (HANDLE hThread,
22 static pSetThreadDescription SetThreadDescriptionFunc;
23 static HMODULE kernel32_module;
24
25 +static void set_thread_description(const char *name);
26 +
27 static bool load_set_thread_description(void)
28 {
29 static gsize _init_once = 0;
@@ -225,6 +227,7 @@ struct QemuThreadData {
227 void *arg;
228 short mode;
229 NotifierList exit;
230 + char *name; /* Freed in win32_start_routine */
231
232 /* Only used for joinable threads. */
233 bool exited;
@@ -266,6 +269,10 @@ static unsigned __stdcall win32_start_routine(void *arg)
269 void *(*start_routine)(void *) = data->start_routine;
270 void *thread_arg = data->arg;
271
272 + if (data->name) {
273 + set_thread_description(data->name);
274 + g_clear_pointer(&data->name, g_free);
275 + }
276 qemu_thread_data = data;
277 qemu_thread_exit(start_routine(thread_arg));
278 abort();
@@ -316,7 +323,7 @@ void *qemu_thread_join(QemuThread *thread)
323 return ret;
324 }
325
319 -static void set_thread_description(HANDLE h, const char *name)
326 +static void set_thread_description(const char *name)
327 {
328 g_autofree wchar_t *namew = NULL;
329
@@ -329,7 +336,7 @@ static void set_thread_description(HANDLE h, const char *name)
336 return;
337 }
338
332 - SetThreadDescriptionFunc(h, namew);
339 + SetThreadDescriptionFunc(GetCurrentThread(), namew);
340 }
341
342 void qemu_thread_create(QemuThread *thread, const char *name,
@@ -344,6 +351,7 @@ void qemu_thread_create(QemuThread *thread, const char *name,
351 data->arg = arg;
352 data->mode = mode;
353 data->exited = false;
354 + data->name = g_strdup(name);
355 notifier_list_init(&data->exit);
356
357 if (data->mode != QEMU_THREAD_DETACHED) {
@@ -355,9 +363,6 @@ void qemu_thread_create(QemuThread *thread, const char *name,
363 if (!hThread) {
364 error_exit(GetLastError(), __func__);
365 }
358 - if (name) {
359 - set_thread_description(hThread, name);
360 - }
366 CloseHandle(hThread);
367
368 thread->data = data;