From c85256b31bee27b099f4b77a8479f6b4a5d53297 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20P=2E=20Berrang=C3=A9?= Date: Fri, 14 Feb 2020 10:44:01 +0000 Subject: [PATCH] src: set the OS level thread name MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Setting the thread name makes it easier to debug libvirtd when many threads are running. Reviewed-by: Michal Privoznik Signed-off-by: Daniel P. Berrangé --- src/libvirt_private.syms | 1 + src/util/virthread.c | 49 ++++++++++++++++++++++++++++++++++------ src/util/virthread.h | 4 +++- 3 files changed, 46 insertions(+), 8 deletions(-) diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 8563695c32..07dee6d841 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -3279,6 +3279,7 @@ virThreadCreateFull; virThreadID; virThreadIsSelf; virThreadJoin; +virThreadMaxName; virThreadSelf; virThreadSelfID; diff --git a/src/util/virthread.c b/src/util/virthread.c index cdc5cab604..40792afdc0 100644 --- a/src/util/virthread.c +++ b/src/util/virthread.c @@ -175,23 +175,57 @@ void virCondBroadcast(virCondPtr c) struct virThreadArgs { virThreadFunc func; - const char *funcName; + char *name; bool worker; void *opaque; }; +size_t virThreadMaxName(void) +{ +#if defined(__FreeBSD__) || defined(__APPLE__) + return 63; +#else +# ifdef __linux__ + return 15; +# else + return 0; /* unlimited */ +# endif +#endif +} + static void *virThreadHelper(void *data) { struct virThreadArgs *args = data; struct virThreadArgs local = *args; + g_autofree char *thname = NULL; + size_t maxname = virThreadMaxName(); /* Free args early, rather than tying it up during the entire thread. */ - VIR_FREE(args); + g_free(args); if (local.worker) - virThreadJobSetWorker(local.funcName); + virThreadJobSetWorker(local.name); else - virThreadJobSet(local.funcName); + virThreadJobSet(local.name); + + if (maxname) { + thname = g_strndup(local.name, maxname); + } else { + thname = g_strdup(local.name); + } + g_free(local.name); + +#if defined(__linux__) || defined(WIN32) + pthread_setname_np(pthread_self(), thname); +#else +# ifdef __FreeBSD__ + pthread_set_name_np(pthread_self(), thname); +# else +# ifdef __APPLE__ + pthread_setname_np(thname); +# endif +# endif +#endif local.func(local.opaque); @@ -204,7 +238,7 @@ static void *virThreadHelper(void *data) int virThreadCreateFull(virThreadPtr thread, bool joinable, virThreadFunc func, - const char *funcName, + const char *name, bool worker, void *opaque) { @@ -221,7 +255,7 @@ int virThreadCreateFull(virThreadPtr thread, } args->func = func; - args->funcName = funcName; + args->name = g_strdup(name); args->worker = worker; args->opaque = opaque; @@ -230,7 +264,8 @@ int virThreadCreateFull(virThreadPtr thread, err = pthread_create(&thread->thread, &attr, virThreadHelper, args); if (err != 0) { - VIR_FREE(args); + g_free(args->name); + g_free(args); goto cleanup; } /* New thread owns 'args' in success case, so don't free */ diff --git a/src/util/virthread.h b/src/util/virthread.h index a7960e444a..c227951ddd 100644 --- a/src/util/virthread.h +++ b/src/util/virthread.h @@ -90,13 +90,15 @@ typedef void (*virThreadFunc)(void *opaque); int virThreadCreateFull(virThreadPtr thread, bool joinable, virThreadFunc func, - const char *funcName, + const char *name, bool worker, void *opaque) G_GNUC_WARN_UNUSED_RESULT; void virThreadSelf(virThreadPtr thread); bool virThreadIsSelf(virThreadPtr thread); void virThreadJoin(virThreadPtr thread); +size_t virThreadMaxName(void); + /* This API is *NOT* for general use. It exists solely as a stub * for integration with libselinux AVC callbacks */ void virThreadCancel(virThreadPtr thread);