summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMark Benvenuto <mark.benvenuto@mongodb.com>2017-04-28 17:43:46 -0400
committerMark Benvenuto <mark.benvenuto@mongodb.com>2017-04-28 17:43:46 -0400
commit4945cdd909c91b4e155a17a07d6766f9ca88be9f (patch)
treeab8207abfd31868728ecdffa198133ca55d0904d
parent858a26bfa16bf0904fe5776e219f8f00b5d864e6 (diff)
downloadmongo-4945cdd909c91b4e155a17a07d6766f9ca88be9f.tar.gz
SERVER-15407 Set Thread Name in Windows, Mac OS X, and Linux
(cherry picked from commit cd675c9e3d80f012bbe654d098a988074bd57abc)
-rw-r--r--src/mongo/util/concurrency/thread_name.cpp70
1 files changed, 70 insertions, 0 deletions
diff --git a/src/mongo/util/concurrency/thread_name.cpp b/src/mongo/util/concurrency/thread_name.cpp
index 8b2b66302b6..670494caab8 100644
--- a/src/mongo/util/concurrency/thread_name.cpp
+++ b/src/mongo/util/concurrency/thread_name.cpp
@@ -25,14 +25,24 @@
* then also delete it in the license file.
*/
+#define MONGO_LOG_DEFAULT_COMPONENT ::mongo::logger::LogComponent::kControl
+
#include "mongo/platform/basic.h"
#include "mongo/util/concurrency/thread_name.h"
#include <boost/thread/tss.hpp>
+#if defined(__APPLE__) || defined(__linux__)
+#include <pthread.h>
+#endif
+#if defined(__APPLE__)
+#include <sys/proc_info.h>
+#endif
+
#include "mongo/base/init.h"
#include "mongo/platform/atomic_word.h"
+#include "mongo/util/log.h"
#include "mongo/util/mongoutils/str.h"
namespace mongo {
@@ -41,6 +51,36 @@ using std::string;
namespace {
+#ifdef _WIN32
+// From https://msdn.microsoft.com/en-us/library/xcb2z8hs.aspx
+// Note: The thread name is only set for the thread if the debugger is attached.
+
+const DWORD MS_VC_EXCEPTION = 0x406D1388;
+#pragma pack(push, 8)
+typedef struct tagTHREADNAME_INFO {
+ DWORD dwType; // Must be 0x1000.
+ LPCSTR szName; // Pointer to name (in user addr space).
+ DWORD dwThreadID; // Thread ID (-1=caller thread).
+ DWORD dwFlags; // Reserved for future use, must be zero.
+} THREADNAME_INFO;
+#pragma pack(pop)
+
+void setWindowsThreadName(DWORD dwThreadID, const char* threadName) {
+ THREADNAME_INFO info;
+ info.dwType = 0x1000;
+ info.szName = threadName;
+ info.dwThreadID = dwThreadID;
+ info.dwFlags = 0;
+#pragma warning(push)
+#pragma warning(disable : 6320 6322)
+ __try {
+ RaiseException(MS_VC_EXCEPTION, 0, sizeof(info) / sizeof(ULONG_PTR), (ULONG_PTR*)&info);
+ } __except (EXCEPTION_EXECUTE_HANDLER) {
+ }
+#pragma warning(pop)
+}
+#endif
+
boost::thread_specific_ptr<std::string> threadName;
AtomicInt64 nextUnnamedThreadId{1};
@@ -62,6 +102,36 @@ MONGO_INITIALIZER(ThreadNameInitializer)(InitializerContext*) {
void setThreadName(StringData name) {
invariant(mongoInitializersHaveRun);
threadName.reset(new string(name.toString()));
+
+#if defined(_WIN32)
+ // Naming should not be expensive compared to thread creation and connection set up, but if
+ // testing shows otherwise we should make this depend on DEBUG again.
+ setWindowsThreadName(GetCurrentThreadId(), threadName->c_str());
+#elif defined(__APPLE__)
+ // Maximum thread name length on OS X is MAXTHREADNAMESIZE (64 characters). This assumes
+ // OS X 10.6 or later.
+ int error = pthread_setname_np(threadName->substr(0, MAXTHREADNAMESIZE - 1).c_str());
+ if (error) {
+ log() << "Ignoring error from setting thread name: " << errnoWithDescription(error);
+ }
+#elif defined(__linux__)
+ // Maximum thread name length supported on Linux is 16 including the null terminator. Ideally
+ // we use short and descriptive thread names that fit: this helps for log readibility as well.
+ // Since several components set verbose thread names with a uniqifier at the end, we do a split
+ // truncation of "first7bytes.last7bytes".
+ int error = 0;
+ if (threadName->size() > 15) {
+ std::string shortName =
+ threadName->substr(0, 7) + '.' + threadName->substr(threadName->size() - 7);
+ error = pthread_setname_np(pthread_self(), shortName.c_str());
+ } else {
+ error = pthread_setname_np(pthread_self(), threadName->c_str());
+ }
+
+ if (error) {
+ log() << "Ignoring error from setting thread name: " << errnoWithDescription(error);
+ }
+#endif
}
const string& getThreadName() {