mirror of
https://github.com/bitcoin/bitcoin.git
synced 2025-03-05 14:06:27 -05:00
util: avoid using thread_local variable that has a destructor
Store the thread name in a `thread_local` variable of type `char[]` instead of `std::string`. This avoids calling the destructor when the thread exits. This is a workaround for https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=278701 For type-safety, return `std::string` from `util::ThreadGetInternalName()` instead of `char[]`. As a side effect of this change, we no longer store a reference to a `thread_local` variable in `CLockLocation`. This was dangerous because if the thread quits while the reference still exists (in the global variable `lock_data`, see inside `GetLockData()`) then the reference will become dangling.
This commit is contained in:
parent
b94061902e
commit
d35ba1b3f1
4 changed files with 27 additions and 21 deletions
|
@ -1049,11 +1049,6 @@ if test "$use_thread_local" = "yes" || test "$use_thread_local" = "auto"; then
|
||||||
dnl https://gist.github.com/jamesob/fe9a872051a88b2025b1aa37bfa98605
|
dnl https://gist.github.com/jamesob/fe9a872051a88b2025b1aa37bfa98605
|
||||||
AC_MSG_RESULT([no])
|
AC_MSG_RESULT([no])
|
||||||
;;
|
;;
|
||||||
*freebsd*)
|
|
||||||
dnl FreeBSD's implementation of thread_local is also buggy (per
|
|
||||||
dnl https://groups.google.com/d/msg/bsdmailinglist/22ncTZAbDp4/Dii_pII5AwAJ)
|
|
||||||
AC_MSG_RESULT([no])
|
|
||||||
;;
|
|
||||||
*)
|
*)
|
||||||
AC_DEFINE([HAVE_THREAD_LOCAL], [1], [Define if thread_local is supported.])
|
AC_DEFINE([HAVE_THREAD_LOCAL], [1], [Define if thread_local is supported.])
|
||||||
AC_MSG_RESULT([yes])
|
AC_MSG_RESULT([yes])
|
||||||
|
|
|
@ -37,11 +37,11 @@ struct CLockLocation {
|
||||||
const char* pszFile,
|
const char* pszFile,
|
||||||
int nLine,
|
int nLine,
|
||||||
bool fTryIn,
|
bool fTryIn,
|
||||||
const std::string& thread_name)
|
std::string&& thread_name)
|
||||||
: fTry(fTryIn),
|
: fTry(fTryIn),
|
||||||
mutexName(pszName),
|
mutexName(pszName),
|
||||||
sourceFile(pszFile),
|
sourceFile(pszFile),
|
||||||
m_thread_name(thread_name),
|
m_thread_name(std::move(thread_name)),
|
||||||
sourceLine(nLine) {}
|
sourceLine(nLine) {}
|
||||||
|
|
||||||
std::string ToString() const
|
std::string ToString() const
|
||||||
|
@ -60,7 +60,7 @@ private:
|
||||||
bool fTry;
|
bool fTry;
|
||||||
std::string mutexName;
|
std::string mutexName;
|
||||||
std::string sourceFile;
|
std::string sourceFile;
|
||||||
const std::string& m_thread_name;
|
const std::string m_thread_name;
|
||||||
int sourceLine;
|
int sourceLine;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
|
|
||||||
#include <config/bitcoin-config.h> // IWYU pragma: keep
|
#include <config/bitcoin-config.h> // IWYU pragma: keep
|
||||||
|
|
||||||
|
#include <cstring>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
@ -40,27 +41,37 @@ static void SetThreadName(const char* name)
|
||||||
// global.
|
// global.
|
||||||
#if defined(HAVE_THREAD_LOCAL)
|
#if defined(HAVE_THREAD_LOCAL)
|
||||||
|
|
||||||
static thread_local std::string g_thread_name;
|
/**
|
||||||
const std::string& util::ThreadGetInternalName() { return g_thread_name; }
|
* The name of the thread. We use char array instead of std::string to avoid
|
||||||
|
* complications with running a destructor when the thread exits. Avoid adding
|
||||||
|
* other thread_local variables.
|
||||||
|
* @see https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=278701
|
||||||
|
*/
|
||||||
|
static thread_local char g_thread_name[128]{'\0'};
|
||||||
|
std::string util::ThreadGetInternalName() { return g_thread_name; }
|
||||||
//! Set the in-memory internal name for this thread. Does not affect the process
|
//! Set the in-memory internal name for this thread. Does not affect the process
|
||||||
//! name.
|
//! name.
|
||||||
static void SetInternalName(std::string name) { g_thread_name = std::move(name); }
|
static void SetInternalName(const std::string& name)
|
||||||
|
{
|
||||||
|
const size_t copy_bytes{std::min(sizeof(g_thread_name) - 1, name.length())};
|
||||||
|
std::memcpy(g_thread_name, name.data(), copy_bytes);
|
||||||
|
g_thread_name[copy_bytes] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
// Without thread_local available, don't handle internal name at all.
|
// Without thread_local available, don't handle internal name at all.
|
||||||
#else
|
#else
|
||||||
|
|
||||||
static const std::string empty_string;
|
std::string util::ThreadGetInternalName() { return ""; }
|
||||||
const std::string& util::ThreadGetInternalName() { return empty_string; }
|
static void SetInternalName(const std::string& name) { }
|
||||||
static void SetInternalName(std::string name) { }
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void util::ThreadRename(std::string&& name)
|
void util::ThreadRename(const std::string& name)
|
||||||
{
|
{
|
||||||
SetThreadName(("b-" + name).c_str());
|
SetThreadName(("b-" + name).c_str());
|
||||||
SetInternalName(std::move(name));
|
SetInternalName(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
void util::ThreadSetInternalName(std::string&& name)
|
void util::ThreadSetInternalName(const std::string& name)
|
||||||
{
|
{
|
||||||
SetInternalName(std::move(name));
|
SetInternalName(name);
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,14 +12,14 @@ namespace util {
|
||||||
//! as its system thread name.
|
//! as its system thread name.
|
||||||
//! @note Do not call this for the main thread, as this will interfere with
|
//! @note Do not call this for the main thread, as this will interfere with
|
||||||
//! UNIX utilities such as top and killall. Use ThreadSetInternalName instead.
|
//! UNIX utilities such as top and killall. Use ThreadSetInternalName instead.
|
||||||
void ThreadRename(std::string&&);
|
void ThreadRename(const std::string&);
|
||||||
|
|
||||||
//! Set the internal (in-memory) name of the current thread only.
|
//! Set the internal (in-memory) name of the current thread only.
|
||||||
void ThreadSetInternalName(std::string&&);
|
void ThreadSetInternalName(const std::string&);
|
||||||
|
|
||||||
//! Get the thread's internal (in-memory) name; used e.g. for identification in
|
//! Get the thread's internal (in-memory) name; used e.g. for identification in
|
||||||
//! logging.
|
//! logging.
|
||||||
const std::string& ThreadGetInternalName();
|
std::string ThreadGetInternalName();
|
||||||
|
|
||||||
} // namespace util
|
} // namespace util
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue