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;