[libvirt] [PATCH] Include a thread identifier in log messages

To allow messages from different threads to be untangled, include an integer thread identifier in log messages. * src/util/logging.c: Include thread ID * src/util/threads.h, src/util/threads.h, src/util/threads-pthread.c: Add new virThreadSelfID() function * configure.ac: Check for sys/syscall.h --- configure.ac | 2 +- src/libvirt_private.syms | 1 + src/util/logging.c | 6 ++++-- src/util/threads-pthread.c | 16 ++++++++++++++++ src/util/threads-win32.c | 16 ++++++++++++++++ src/util/threads.h | 1 + 6 files changed, 39 insertions(+), 3 deletions(-) diff --git a/configure.ac b/configure.ac index b912a7a..af1dfec 100644 --- a/configure.ac +++ b/configure.ac @@ -110,7 +110,7 @@ LIBS=$old_libs dnl Availability of various common headers (non-fatal if missing). AC_CHECK_HEADERS([pwd.h paths.h regex.h sys/syslimits.h sys/un.h \ sys/poll.h syslog.h mntent.h net/ethernet.h linux/magic.h \ - sys/un.h]) + sys/un.h sys/syscall.h]) AC_CHECK_LIB([intl],[gettext],[]) diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index e808375..3bb1762 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -781,6 +781,7 @@ virThreadCreate; virThreadIsSelf; virThreadJoin; virThreadSelf; +virThreadSelfID; # usb.h diff --git a/src/util/logging.c b/src/util/logging.c index ac38d4d..d65dec0 100644 --- a/src/util/logging.c +++ b/src/util/logging.c @@ -548,14 +548,16 @@ void virLogMessage(const char *category, int priority, const char *funcname, localtime_r(&cur_time.tv_sec, &time_info); if ((funcname != NULL)) { - ret = virAsprintf(&msg, "%02d:%02d:%02d.%03d: %s : %s:%lld : %s\n", + ret = virAsprintf(&msg, "%02d:%02d:%02d.%03d: %d: %s : %s:%lld : %s\n", time_info.tm_hour, time_info.tm_min, time_info.tm_sec, (int) cur_time.tv_usec / 1000, + virThreadSelfID(), virLogPriorityString(priority), funcname, linenr, str); } else { - ret = virAsprintf(&msg, "%02d:%02d:%02d.%03d: %s : %s\n", + ret = virAsprintf(&msg, "%02d:%02d:%02d.%03d: %d: %s : %s\n", time_info.tm_hour, time_info.tm_min, time_info.tm_sec, (int) cur_time.tv_usec / 1000, + virThreadSelfID(), virLogPriorityString(priority), str); } VIR_FREE(str); diff --git a/src/util/threads-pthread.c b/src/util/threads-pthread.c index 34d9ce8..02070ae 100644 --- a/src/util/threads-pthread.c +++ b/src/util/threads-pthread.c @@ -21,6 +21,11 @@ #include <config.h> +#include <unistd.h> +#if HAVE_SYS_SYSCALL_H +# include <sys/syscall.h> +#endif + /* Nothing special required for pthreads */ int virThreadInitialize(void) @@ -170,6 +175,17 @@ bool virThreadIsSelf(virThreadPtr thread) return pthread_equal(pthread_self(), thread->thread) ? true : false; } +int virThreadSelfID(void) +{ +#if defined(HAVE_SYS_SYSCALL_H) && defined(SYS_gettid) + pid_t tid; + tid = syscall(SYS_gettid); + return (int)tid; +#else + return (int)pthread_self(); +#endif +} + void virThreadJoin(virThreadPtr thread) { pthread_join(thread->thread, NULL); diff --git a/src/util/threads-win32.c b/src/util/threads-win32.c index de73fd5..45c7eef 100644 --- a/src/util/threads-win32.c +++ b/src/util/threads-win32.c @@ -288,6 +288,22 @@ bool virThreadIsSelf(virThreadPtr thread) return self.thread == thread->thread ? true : false; } +int virThreadSelfID(void) +{ + HANDLE handle = GetCurrentThread(); + HANDLE process = GetCurrentProcess(); + HANDLE thread; + int id; + + DuplicateHandle(process, handle, process, + &thread, 0, FALSE, + DUPLICATE_SAME_ACCESS); + id = (int)thread; + CloseHandle(thread); + return id; +} + + void virThreadJoin(virThreadPtr thread) { if (thread->joinable) { diff --git a/src/util/threads.h b/src/util/threads.h index b3b827d..fa00a91 100644 --- a/src/util/threads.h +++ b/src/util/threads.h @@ -51,6 +51,7 @@ int virThreadCreate(virThreadPtr thread, void virThreadSelf(virThreadPtr thread); bool virThreadIsSelf(virThreadPtr thread); void virThreadJoin(virThreadPtr thread); +int virThreadSelfID(void); int virMutexInit(virMutexPtr m) ATTRIBUTE_RETURN_CHECK; int virMutexInitRecursive(virMutexPtr m) ATTRIBUTE_RETURN_CHECK; -- 1.7.2.3

On 11/22/2010 07:10 AM, Daniel P. Berrange wrote:
To allow messages from different threads to be untangled, include an integer thread identifier in log messages.
* src/util/logging.c: Include thread ID * src/util/threads.h, src/util/threads.h, src/util/threads-pthread.c: Add new virThreadSelfID() function * configure.ac: Check for sys/syscall.h
+int virThreadSelfID(void) +{ +#if defined(HAVE_SYS_SYSCALL_H) && defined(SYS_gettid) + pid_t tid; + tid = syscall(SYS_gettid); + return (int)tid;
Bummer that glibc doesn't export gettid(), but this looks correct to me for Linux.
+#else + return (int)pthread_self();
According to POSIX, this is not portable: pthread_t is an opaque type and is allowed to be a struct rather than an arithmetic type, in which case casting to int will cause a compilation failure. But in practice: pthread_t is integral on Linux, Solaris, and AIX; and a pointer type on BSD and Cygwin; therefore, the cast will probably succeed on all architectures we might encounter, but it still might not be correct (that is, since pthread_equal() is allowed to return true for two distinct pointers, merely casting a pointer to int may give different ids for the same thread). But I'm okay waiting for an actual bug report of this failing to do the right thing before we change this code. -- Eric Blake eblake@redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org

On 11/22/2010 11:44 AM, Eric Blake wrote:
On 11/22/2010 07:10 AM, Daniel P. Berrange wrote:
To allow messages from different threads to be untangled, include an integer thread identifier in log messages.
* src/util/logging.c: Include thread ID * src/util/threads.h, src/util/threads.h, src/util/threads-pthread.c: Add new virThreadSelfID() function * configure.ac: Check for sys/syscall.h
But I'm okay waiting for an actual bug report of this failing to do the right thing before we change this code.
Just so I'm clear: ACK for applying as-is -- Eric Blake eblake@redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org

On Mon, Nov 22, 2010 at 11:44:42AM -0700, Eric Blake wrote:
On 11/22/2010 07:10 AM, Daniel P. Berrange wrote:
To allow messages from different threads to be untangled, include an integer thread identifier in log messages.
* src/util/logging.c: Include thread ID * src/util/threads.h, src/util/threads.h, src/util/threads-pthread.c: Add new virThreadSelfID() function * configure.ac: Check for sys/syscall.h
+int virThreadSelfID(void) +{ +#if defined(HAVE_SYS_SYSCALL_H) && defined(SYS_gettid) + pid_t tid; + tid = syscall(SYS_gettid); + return (int)tid;
Bummer that glibc doesn't export gettid(), but this looks correct to me for Linux.
+#else + return (int)pthread_self();
According to POSIX, this is not portable: pthread_t is an opaque type and is allowed to be a struct rather than an arithmetic type, in which case casting to int will cause a compilation failure. But in practice: pthread_t is integral on Linux, Solaris, and AIX; and a pointer type on BSD and Cygwin; therefore, the cast will probably succeed on all architectures we might encounter, but it still might not be correct (that is, since pthread_equal() is allowed to return true for two distinct pointers, merely casting a pointer to int may give different ids for the same thread).
But I'm okay waiting for an actual bug report of this failing to do the right thing before we change this code.
Agreed, given that this is only used for outputing a log message, I don't think the potential problems are worth worrying about at this point in time. Daniel

2010/11/22 Daniel P. Berrange <berrange@redhat.com>:
To allow messages from different threads to be untangled, include an integer thread identifier in log messages.
+int virThreadSelfID(void) +{ + HANDLE handle = GetCurrentThread(); + HANDLE process = GetCurrentProcess(); + HANDLE thread; + int id; + + DuplicateHandle(process, handle, process, + &thread, 0, FALSE, + DUPLICATE_SAME_ACCESS); + id = (int)thread; + CloseHandle(thread); + return id; +}
You could use GetCurrentThreadId() here instead of the handle value. Matthias
participants (3)
-
Daniel P. Berrange
-
Eric Blake
-
Matthias Bolte