Add support for getting the current thread's name
authorChristopher Dykes <cdykes@fb.com>
Thu, 4 May 2017 23:31:01 +0000 (16:31 -0700)
committerFacebook Github Bot <facebook-github-bot@users.noreply.github.com>
Thu, 4 May 2017 23:36:31 +0000 (16:36 -0700)
Summary: It's primarily for use in testing, but is useful for log output as well.

Reviewed By: yfeldblum

Differential Revision: D4943072

fbshipit-source-id: 0ca259d6c90f439e733a6179e7cba85dcd1ec9e7

folly/ThreadName.cpp
folly/ThreadName.h
folly/test/ThreadNameTest.cpp

index a24a6b8..97db551 100644 (file)
@@ -57,6 +57,30 @@ bool canSetOtherThreadName() {
 #endif
 }
 
+static constexpr size_t kMaxThreadNameLength = 16;
+
+Optional<std::string> getCurrentThreadName() {
+#if !FOLLY_HAVE_PTHREAD
+  return Optional<std::string>();
+#else
+#if FOLLY_HAS_PTHREAD_SETNAME_NP_THREAD_NAME
+  std::array<char, kMaxThreadNameLength> buf;
+  if (pthread_getname_np(pthread_self(), buf.data(), buf.size()) != 0) {
+    return Optional<std::string>();
+  }
+  return make_optional(std::string(buf.data()));
+#elif FOLLY_HAS_PTHREAD_SETNAME_NP_NAME
+  std::array<char, kMaxThreadNameLength> buf;
+  if (pthread_getname_np(buf.data(), buf.size()) != 0) {
+    return Optional<std::string>();
+  }
+  return make_optional(std::string(buf.data()));
+#else
+  return Optional<std::string>();
+#endif
+#endif
+}
+
 bool setThreadName(std::thread::id tid, StringPiece name) {
 #if !FOLLY_HAVE_PTHREAD || _WIN32
   return false;
@@ -73,13 +97,14 @@ bool setThreadName(std::thread::id tid, StringPiece name) {
   // extract it.
   pthread_t id;
   std::memcpy(&id, &tid, sizeof(id));
+  auto trimmedName = name.fbstr().substr(0, kMaxThreadNameLength - 1);
 #if FOLLY_HAS_PTHREAD_SETNAME_NP_THREAD_NAME
-  return 0 == pthread_setname_np(id, name.fbstr().substr(0, 15).c_str());
+  return 0 == pthread_setname_np(id, trimmedName.c_str());
 #elif FOLLY_HAS_PTHREAD_SETNAME_NP_NAME
   // Since OS X 10.6 it is possible for a thread to set its own name,
   // but not that of some other thread.
   if (pthread_equal(pthread_self(), id)) {
-    return 0 == pthread_setname_np(name.fbstr().c_str());
+    return 0 == pthread_setname_np(trimmedName.c_str());
   }
   return false;
 #else
index b55793c..d78e2fa 100644 (file)
 
 #pragma once
 
+#include <string>
 #include <thread>
 
+#include <folly/Optional.h>
 #include <folly/Range.h>
 #include <folly/portability/Config.h>
 #include <folly/portability/PThread.h>
@@ -33,6 +35,10 @@ bool canSetCurrentThreadName();
  * threads other than the one currently executing.
  */
 bool canSetOtherThreadName();
+/**
+ * Get the name of the current string, or nothing if an error occurs.
+ */
+Optional<std::string> getCurrentThreadName();
 
 bool setThreadName(std::thread::id tid, StringPiece name);
 #if FOLLY_HAVE_PTHREAD
index 57eae21..b804bbb 100644 (file)
@@ -27,6 +27,17 @@ using namespace folly;
 static bool expectedSetOtherThreadNameResult = folly::canSetOtherThreadName();
 static bool expectedSetSelfThreadNameResult = folly::canSetCurrentThreadName();
 
+TEST(ThreadName, getCurrentThreadName) {
+  static constexpr StringPiece kThreadName{"rockin-thread"};
+  thread th([] {
+    EXPECT_EQ(expectedSetSelfThreadNameResult, setThreadName(kThreadName));
+    if (expectedSetSelfThreadNameResult) {
+      EXPECT_EQ(kThreadName.toString(), getCurrentThreadName().value());
+    }
+  });
+  SCOPE_EXIT { th.join(); };
+}
+
 TEST(ThreadName, setThreadName_self) {
   thread th([] {
     EXPECT_EQ(expectedSetSelfThreadNameResult, setThreadName("rockin-thread"));