diff --git a/src/Makefile.am b/src/Makefile.am index bc1c45ac51..d9255cac92 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -165,6 +165,8 @@ BITCOIN_CORE_H = \ util.h \ utilmemory.h \ utilmoneystr.h \ + utilthread.h \ + utilthreadnames.h \ utiltime.h \ utilstring.h \ validation.h \ @@ -377,6 +379,8 @@ libdogecoin_util_a_SOURCES = \ util.cpp \ utilmoneystr.cpp \ utilstrencodings.cpp \ + utilthread.cpp \ + utilthreadnames.cpp \ utiltime.cpp \ $(BITCOIN_CORE_H) diff --git a/src/sync.cpp b/src/sync.cpp index 3188242009..52840c177b 100644 --- a/src/sync.cpp +++ b/src/sync.cpp @@ -6,6 +6,7 @@ #include "util.h" #include "utilstrencodings.h" +#include "utilthreadnames.h" #include diff --git a/src/utilthread.cpp b/src/utilthread.cpp new file mode 100644 index 0000000000..3e654145e1 --- /dev/null +++ b/src/utilthread.cpp @@ -0,0 +1,26 @@ +// Copyright (c) 2021 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#include + +#include +#include + +#include + +void util::TraceThread(const char* thread_name, std::function thread_func) +{ + util::ThreadRename(thread_name); + try { + LogPrintf("%s thread start\n", thread_name); + thread_func(); + LogPrintf("%s thread exit\n", thread_name); + } catch (const std::exception& e) { + PrintExceptionContinue(&e, thread_name); + throw; + } catch (...) { + PrintExceptionContinue(nullptr, thread_name); + throw; + } +} diff --git a/src/utilthread.h b/src/utilthread.h new file mode 100644 index 0000000000..009bd8091c --- /dev/null +++ b/src/utilthread.h @@ -0,0 +1,18 @@ +// Copyright (c) 2021 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#ifndef BITCOIN_UTILTHREAD_H +#define BITCOIN_UTILTHREAD_H + +#include + +namespace util { +/** + * A wrapper for do-something-once thread functions. + */ +void TraceThread(const char* thread_name, std::function thread_func); + +} // namespace util + +#endif // BITCOIN_UTILTHREAD_H diff --git a/src/utilthreadnames.cpp b/src/utilthreadnames.cpp new file mode 100644 index 0000000000..9e18fbb636 --- /dev/null +++ b/src/utilthreadnames.cpp @@ -0,0 +1,68 @@ +// Copyright (c) 2018-2019 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#if defined(HAVE_CONFIG_H) +#include +#endif + +#include +#include +#include + +#if (defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__DragonFly__)) +#include +#include +#endif + +#include + +#ifdef HAVE_SYS_PRCTL_H +#include +#endif + +//! Set the thread's name at the process level. Does not affect the +//! internal name. +static void SetThreadName(const char* name) +{ +#if defined(PR_SET_NAME) + // Only the first 15 characters are used (16 - NUL terminator) + ::prctl(PR_SET_NAME, name, 0, 0, 0); +#elif (defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__DragonFly__)) + pthread_set_name_np(pthread_self(), name); +#elif defined(MAC_OSX) + pthread_setname_np(name); +#else + // Prevent warnings for unused parameters... + (void)name; +#endif +} + +// If we have thread_local, just keep thread ID and name in a thread_local +// global. +#if defined(HAVE_THREAD_LOCAL) + +static thread_local std::string g_thread_name; +const std::string& util::ThreadGetInternalName() { return g_thread_name; } +//! Set the in-memory internal name for this thread. Does not affect the process +//! name. +static void SetInternalName(std::string name) { g_thread_name = std::move(name); } + +// Without thread_local available, don't handle internal name at all. +#else + +static const std::string empty_string; +const std::string& util::ThreadGetInternalName() { return empty_string; } +static void SetInternalName(std::string name) { } +#endif + +void util::ThreadRename(std::string&& name) +{ + SetThreadName(("b-" + name).c_str()); + SetInternalName(std::move(name)); +} + +void util::ThreadSetInternalName(std::string&& name) +{ + SetInternalName(std::move(name)); +} diff --git a/src/utilthreadnames.h b/src/utilthreadnames.h new file mode 100644 index 0000000000..dd99fdca3d --- /dev/null +++ b/src/utilthreadnames.h @@ -0,0 +1,26 @@ +// Copyright (c) 2018-2019 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#ifndef BITCOIN_UTILTHREADNAMES_H +#define BITCOIN_UTILTHREADNAMES_H + +#include + +namespace util { +//! Rename a thread both in terms of an internal (in-memory) name as well +//! as its system thread name. +//! @note Do not call this for the main thread, as this will interfere with +//! UNIX utilities such as top and killall. Use ThreadSetInternalName instead. +void ThreadRename(std::string&&); + +//! Set the internal (in-memory) name of the current thread only. +void ThreadSetInternalName(std::string&&); + +//! Get the thread's internal (in-memory) name; used e.g. for identification in +//! logging. +const std::string& ThreadGetInternalName(); + +} // namespace util + +#endif // BITCOIN_UTILTHREADNAMES_H