From cb8d0d245b5739e7493dcf27314f6e42615f14b1 Mon Sep 17 00:00:00 2001 From: Michael Jeanson Date: Wed, 12 Aug 2020 17:08:07 -0400 Subject: [PATCH] Add common util to set thread name MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Use the same code to set all the thread names and fail gracefully on platforms that don't support them. This sets the minimum requirement for thread names on Linux to Glibc >= 2.12, which seems reasonable. Signed-off-by: Michael Jeanson Signed-off-by: Jérémie Galarneau Change-Id: I61c0b9adb6c2309fed91b5a1b11ebc5ee2a637ce --- configure.ac | 3 ++ m4/lttng_pthread_setname_np.m4 | 70 ++++++++++++++++++++++++++++++++++ src/common/Makefile.am | 1 + src/common/compat/Makefile.am | 2 +- src/common/compat/prctl.h | 36 ----------------- src/common/compat/pthread.h | 36 +++++++++++++++++ src/common/error.c | 14 ++----- src/common/runas.c | 7 ++-- src/common/thread.c | 31 +++++++++++++++ src/common/thread.h | 21 ++++++++++ 10 files changed, 170 insertions(+), 51 deletions(-) create mode 100644 m4/lttng_pthread_setname_np.m4 delete mode 100644 src/common/compat/prctl.h create mode 100644 src/common/compat/pthread.h create mode 100644 src/common/thread.c create mode 100644 src/common/thread.h diff --git a/configure.ac b/configure.ac index c6b83b78a..dd0fb21da 100644 --- a/configure.ac +++ b/configure.ac @@ -237,6 +237,9 @@ AC_CHECK_FUNCS([ \ sched_getcpu sysconf sync_file_range ]) +# Check for pthread_setname_np and its signature +LTTNG_PTHREAD_SETNAME_NP + # Check if clock_gettime, timer_create, timer_settime, and timer_delete are available in lib rt, and if so, # add -lrt to LIBS AC_CHECK_LIB([rt], [clock_gettime, timer_create, timer_settime, timer_delete]) diff --git a/m4/lttng_pthread_setname_np.m4 b/m4/lttng_pthread_setname_np.m4 new file mode 100644 index 000000000..a8526e8d2 --- /dev/null +++ b/m4/lttng_pthread_setname_np.m4 @@ -0,0 +1,70 @@ +# SYNOPSIS +# +# LTTNG_PTHREAD_SETNAME_NP +# +# LICENSE +# +# Copyright (c) 2020 Michael Jeanson +# +# This program is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by the +# Free Software Foundation; either version 2 of the License, or (at your +# option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General +# Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program. If not, see . +# +# As a special exception, the respective Autoconf Macro's copyright owner +# gives unlimited permission to copy, distribute and modify the configure +# scripts that are the output of Autoconf when processing the Macro. You +# need not follow the terms of the GNU General Public License when using +# or distributing such scripts, even though portions of the text of the +# Macro appear in them. The GNU General Public License (GPL) does govern +# all other use of the material that constitutes the Autoconf Macro. +# +# This special exception to the GPL applies to versions of the Autoconf +# Macro released by the Autoconf Archive. When you make and distribute a +# modified version of the Autoconf Macro, you may extend this special +# exception to the GPL to apply to your modified version as well. + +AC_DEFUN([LTTNG_PTHREAD_SETNAME_NP], [ +AC_REQUIRE([AX_PTHREAD]) +AC_LANG_PUSH([C]) + +lttng_pthread_setname_np_save_LDFLAGS="$LDFLAGS" +lttng_pthread_setname_np_save_LIBS="$LIBS" +LDFLAGS="$LDFLAGS $PTHREAD_CFLAGS" +LIBS="$LIBS $PTHREAD_LIBS" + +# GLIBC >= 2.12, Solaris >= 11.3 +AC_MSG_CHECKING(for pthread_setname_np(pthread_t, const char*)) +AC_LINK_IFELSE( + [AC_LANG_PROGRAM( + [#include ], + [pthread_setname_np(pthread_self(), "example")])], + [AC_MSG_RESULT(yes) + AC_DEFINE(HAVE_PTHREAD_SETNAME_NP_WITH_TID,1, + [Have function pthread_setname_np(pthread_t, const char*)])], + [AC_MSG_RESULT(no)]) + +# MacOS X >= 10.6, iOS >= 3.2 +AC_MSG_CHECKING(for pthread_setname_np(const char*)) +AC_LINK_IFELSE( + [AC_LANG_PROGRAM( + [#include ], + [pthread_setname_np("example")])], + [AC_MSG_RESULT(yes) + AC_DEFINE(HAVE_PTHREAD_SETNAME_NP_WITHOUT_TID,1, + [Have function pthread_setname_np(const char*)])], + [AC_MSG_RESULT(no)]) + +LDFLAGS=$lttng_pthread_setname_np_save_LDFLAGS +LIBS=$lttng_pthread_setname_np_save_LIBS + +AC_LANG_POP +])dnl LTTNG_PTHREAD_SETNAME_NP diff --git a/src/common/Makefile.am b/src/common/Makefile.am index 6a841e92a..6ee43e48f 100644 --- a/src/common/Makefile.am +++ b/src/common/Makefile.am @@ -75,6 +75,7 @@ libcommon_la_SOURCES = \ userspace-probe.c \ utils.c utils.h \ uuid.c uuid.h \ + thread.c thread.h \ tracker.c tracker.h \ waiter.c waiter.h diff --git a/src/common/compat/Makefile.am b/src/common/compat/Makefile.am index 2430fceab..0878b00c2 100644 --- a/src/common/compat/Makefile.am +++ b/src/common/compat/Makefile.am @@ -10,5 +10,5 @@ endif libcompat_la_SOURCES = poll.h fcntl.h endian.h mman.h dirent.h \ socket.h compat-fcntl.c tid.h \ - getenv.h string.h prctl.h paths.h netdb.h $(COMPAT) \ + getenv.h string.h paths.h pthread.h netdb.h $(COMPAT) \ time.h directory-handle.h directory-handle.c path.h diff --git a/src/common/compat/prctl.h b/src/common/compat/prctl.h deleted file mode 100644 index 197b39396..000000000 --- a/src/common/compat/prctl.h +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright (C) 2015 Jérémie Galarneau - * - * SPDX-License-Identifier: GPL-2.0-only - * - */ - -#ifndef _COMPAT_PRCTL_H -#define _COMPAT_PRCTL_H - -#ifdef __linux__ -#include - -static inline -int lttng_prctl(int option, unsigned long arg2, unsigned long arg3, - unsigned long arg4, unsigned long arg5) -{ - return prctl(option, arg2, arg3, arg4, arg5); -} - -#else - -#ifndef PR_SET_NAME -#define PR_SET_NAME 0 -#endif /* PR_SET_NAME */ - -static inline -int lttng_prctl(int option, unsigned long arg2, unsigned long arg3, - unsigned long arg4, unsigned long arg5) -{ - return -ENOSYS; -} - -#endif /* __linux__ */ - -#endif /* _COMPAT_PRCTL_H */ diff --git a/src/common/compat/pthread.h b/src/common/compat/pthread.h new file mode 100644 index 000000000..a5f91b339 --- /dev/null +++ b/src/common/compat/pthread.h @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2020 Michael Jeanson + * + * SPDX-License-Identifier: GPL-2.0-only + * + */ + +#ifndef _COMPAT_PTHREAD_H +#define _COMPAT_PTHREAD_H + +#include + +#if defined(HAVE_PTHREAD_SETNAME_NP_WITH_TID) +static inline +int lttng_pthread_setname_np(const char *name) +{ + return pthread_setname_np(pthread_self(), name); +} +#elif defined(HAVE_PTHREAD_SETNAME_NP_WITHOUT_TID) +static inline +int lttng_pthread_setname_np(const char *name) +{ + return pthread_setname_np(name); +} +#else +/* + * For platforms without thread name support, do nothing. + */ +static inline +int lttng_pthread_setname_np(const char *name) +{ + return -ENOSYS; +} +#endif + +#endif /* _COMPAT_PTHREAD_H */ diff --git a/src/common/error.c b/src/common/error.c index 82190b9fd..11dbc9028 100644 --- a/src/common/error.c +++ b/src/common/error.c @@ -14,6 +14,7 @@ #include #include +#include #include #include @@ -77,16 +78,9 @@ void logger_set_thread_name(const char *name, bool set_pthread_name) URCU_TLS(logger_thread_name) = name; if (set_pthread_name) { - char pthread_name[16]; - - /* - * Truncations are expected since pthread limits thread names to - * a generous 16 characters. - */ - strncpy(pthread_name, name, sizeof(pthread_name)); - pthread_name[sizeof(pthread_name) - 1] = '\0'; - ret = pthread_setname_np(pthread_self(), pthread_name); - if (ret) { + ret = lttng_thread_setname(name); + if (ret && ret != -ENOSYS) { + /* Don't fail as this is not essential. */ DBG("Failed to set pthread name attribute"); } } diff --git a/src/common/runas.c b/src/common/runas.c index 28bcff30a..b1a4b4836 100644 --- a/src/common/runas.c +++ b/src/common/runas.c @@ -27,10 +27,10 @@ #include #include #include -#include #include #include #include +#include #include @@ -958,11 +958,10 @@ int run_as_worker(struct run_as_worker *worker) memset(worker->procname, 0, proc_orig_len); strncpy(worker->procname, DEFAULT_RUN_AS_WORKER_NAME, proc_orig_len); - ret = lttng_prctl(PR_SET_NAME, - (unsigned long) DEFAULT_RUN_AS_WORKER_NAME, 0, 0, 0); + ret = lttng_thread_setname(DEFAULT_RUN_AS_WORKER_NAME); if (ret && ret != -ENOSYS) { /* Don't fail as this is not essential. */ - PERROR("prctl PR_SET_NAME"); + DBG("Failed to set pthread name attribute"); } memset(&sendret, 0, sizeof(sendret)); diff --git a/src/common/thread.c b/src/common/thread.c new file mode 100644 index 000000000..bbcc1521c --- /dev/null +++ b/src/common/thread.c @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2020 Michael Jeanson + * + * SPDX-License-Identifier: LGPL-2.1-only + * + */ + +#include + +#include +#include "thread.h" + +#define LTTNG_PTHREAD_NAMELEN 16 + +int lttng_thread_setname(const char *name) +{ + int ret; + char pthread_name[LTTNG_PTHREAD_NAMELEN]; + + /* + * Truncations are expected since pthread limits thread names to + * a generous 16 characters. + */ + strncpy(pthread_name, name, sizeof(pthread_name)); + pthread_name[sizeof(pthread_name) - 1] = '\0'; + + ret = lttng_pthread_setname_np(pthread_name); + + return ret; +} + diff --git a/src/common/thread.h b/src/common/thread.h new file mode 100644 index 000000000..b73172269 --- /dev/null +++ b/src/common/thread.h @@ -0,0 +1,21 @@ +/* + * Copyright (C) 2020 Michael Jeanson + * + * SPDX-License-Identifier: LGPL-2.1-only + * + */ + +#ifndef LTTNG_THREAD_H +#define LTTNG_THREAD_H + +#include + +/* + * Set the current thread name on platforms that support it. The name can + * be of arbitrary length and will be truncated to the platform limit, + * usually 16. + */ +LTTNG_HIDDEN +int lttng_thread_setname(const char *name); + +#endif /* LTTNG_THREAD_H */ -- 2.34.1