diff options
author | evan@chromium.org <evan@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-06-10 22:55:17 +0000 |
---|---|---|
committer | evan@chromium.org <evan@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-06-10 22:55:17 +0000 |
commit | 633d4a34b28c914102342ef7042f643fff3a4451 (patch) | |
tree | 5ee89f5e0fcb3bd9888db99f825afe4c0b402d55 /base | |
parent | c844680f54d4b7e22656b947be29722ef9177d60 (diff) | |
download | chromium_src-633d4a34b28c914102342ef7042f643fff3a4451.zip chromium_src-633d4a34b28c914102342ef7042f643fff3a4451.tar.gz chromium_src-633d4a34b28c914102342ef7042f643fff3a4451.tar.bz2 |
posix: set thread names
There's a non-portable function for doing this: pthread_setname_np.
It's supported by OS X >= 10.6 and the Xcode debugger will show the thread
names if they're provided. On Linux, support has just recently been added
to glibc for the same function. Since OS coverage of the function is so
spotty, we look for the symbol at runtime; on Linux we fall back to another
implementation of the same functionality if the function isn't available.
[reland of r49212, with Mac fixed and Linux disabled; see
comments in code as to why Linux is disabled]
Review URL: http://codereview.chromium.org/2774001
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@49465 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'base')
-rw-r--r-- | base/platform_thread_mac.mm | 21 | ||||
-rw-r--r-- | base/platform_thread_posix.cc | 58 |
2 files changed, 71 insertions, 8 deletions
diff --git a/base/platform_thread_mac.mm b/base/platform_thread_mac.mm index 46ac241..d155b323 100644 --- a/base/platform_thread_mac.mm +++ b/base/platform_thread_mac.mm @@ -5,8 +5,10 @@ #include "base/platform_thread.h" #import <Foundation/Foundation.h> +#include <dlfcn.h> #include "base/logging.h" +#include "base/safe_strerror_posix.h" // A simple class that demonstrates our impressive ability to do nothing. @interface NoOp : NSObject @@ -46,3 +48,22 @@ void InitThreading() { } } // namespace base + +// static +void PlatformThread::SetName(const char* name) { + // pthread_setname_np is only available in 10.6 or later, so test + // for it at runtime. + int (*dynamic_pthread_setname_np)(const char*); + *reinterpret_cast<void**>(&dynamic_pthread_setname_np) = + dlsym(RTLD_DEFAULT, "pthread_setname_np"); + if (!dynamic_pthread_setname_np) + return; + + // Mac OS X does not expose the length limit of the name, so + // hardcode it. + const int kMaxNameLength = 63; + std::string shortened_name = std::string(name).substr(0, kMaxNameLength); + int err = dynamic_pthread_setname_np(shortened_name.c_str()); + if (err < 0) + LOG(ERROR) << "pthread_setname_np: " << safe_strerror(err); +} diff --git a/base/platform_thread_posix.cc b/base/platform_thread_posix.cc index 16fd529..040452e 100644 --- a/base/platform_thread_posix.cc +++ b/base/platform_thread_posix.cc @@ -4,6 +4,7 @@ #include "base/platform_thread.h" +#include <dlfcn.h> #include <errno.h> #include <sched.h> @@ -11,15 +12,21 @@ #include <mach/mach.h> #include <sys/resource.h> #include <algorithm> -#else +#endif + +#if defined(OS_LINUX) +#include <sys/prctl.h> #include <sys/syscall.h> #include <unistd.h> #endif +#include "base/logging.h" +#include "base/safe_strerror_posix.h" + #if defined(OS_MACOSX) namespace base { void InitThreading(); -} // namespace +} // namespace base #endif static void* ThreadFunc(void* closure) { @@ -63,15 +70,50 @@ void PlatformThread::Sleep(int duration_ms) { sleep_time = remaining; } +// Linux SetName is currently disabled, as we need to distinguish between +// helper threads (where it's ok to make this call) and the main thread +// (where making this call renames our process, causing tools like killall +// to stop working). +#if 0 && defined(OS_LINUX) +// static +void PlatformThread::SetName(const char* name) { + // http://0pointer.de/blog/projects/name-your-threads.html + + // glibc recently added support for pthread_setname_np, but it's not + // commonly available yet. So test for it at runtime. + int (*dynamic_pthread_setname_np)(pthread_t, const char*); + *reinterpret_cast<void**>(&dynamic_pthread_setname_np) = + dlsym(RTLD_DEFAULT, "pthread_setname_np"); + + if (dynamic_pthread_setname_np) { + // This limit comes from glibc, which gets it from the kernel + // (TASK_COMM_LEN). + const int kMaxNameLength = 15; + std::string shortened_name = std::string(name).substr(0, kMaxNameLength); + int err = dynamic_pthread_setname_np(pthread_self(), + shortened_name.c_str()); + if (err < 0) + LOG(ERROR) << "pthread_setname_np: " << safe_strerror(err); + } else { + // Implementing this function without glibc is simple enough. (We + // don't do the name length clipping as above because it will be + // truncated by the callee (see TASK_COMM_LEN above).) + int err = prctl(PR_SET_NAME, name); + if (err < 0) + PLOG(ERROR) << "prctl(PR_SET_NAME)"; + } +} +#elif defined(OS_MACOSX) +// Mac is implemented in platform_thread_mac.mm. +#else // static void PlatformThread::SetName(const char* name) { - // The POSIX standard does not provide for naming threads, and neither Linux - // nor Mac OS X (our two POSIX targets) provide any non-portable way of doing - // it either. (Some BSDs provide pthread_set_name_np but that isn't much of a - // consolation prize.) - // TODO(darin): decide whether stuffing the name in TLS or other in-memory - // structure would be useful for debugging or not. + // Leave it unimplemented. + + // (This should be relatively simple to implement for the BSDs; I + // just don't have one handy to test the code on.) } +#endif // defined(OS_LINUX) namespace { |