Skip to content

Commit ae5f2b6

Browse files
committed
threads: introduce util/threadnames, refactor thread naming
This work is prerequisite to attaching thread names to log lines and deadlock debug utilities. This code allows setting of an "internal" threadname per thread on platforms where thread_local is available. This commit also moves RenameThread() out of a more general module and adds a numeric suffix to disambiguate between threads with the same name. It explicitly names a few main threads using the new util::ThreadRename().
1 parent 188ca75 commit ae5f2b6

File tree

12 files changed

+103
-36
lines changed

12 files changed

+103
-36
lines changed

src/Makefile.am

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -210,6 +210,7 @@ BITCOIN_CORE_H = \
210210
util/memory.h \
211211
util/moneystr.h \
212212
util/rbf.h \
213+
util/threadnames.h \
213214
util/time.h \
214215
util/url.h \
215216
util/validation.h \
@@ -491,6 +492,7 @@ libbitcoin_util_a_SOURCES = \
491492
util/system.cpp \
492493
util/moneystr.cpp \
493494
util/rbf.cpp \
495+
util/threadnames.cpp \
494496
util/strencodings.cpp \
495497
util/time.cpp \
496498
util/url.cpp \

src/bitcoind.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#include <util/system.h>
2020
#include <httpserver.h>
2121
#include <httprpc.h>
22+
#include <util/threadnames.h>
2223
#include <util/strencodings.h>
2324
#include <walletinitinterface.h>
2425

@@ -64,6 +65,8 @@ static bool AppInit(int argc, char* argv[])
6465

6566
bool fRet = false;
6667

68+
util::ThreadRename("init");
69+
6770
//
6871
// Parameters
6972
//

src/httpserver.cpp

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
#include <chainparamsbase.h>
88
#include <compat.h>
9+
#include <util/threadnames.h>
910
#include <util/system.h>
1011
#include <util/strencodings.h>
1112
#include <netbase.h>
@@ -17,7 +18,7 @@
1718
#include <memory>
1819
#include <stdio.h>
1920
#include <stdlib.h>
20-
#include <string.h>
21+
#include <string>
2122

2223
#include <sys/types.h>
2324
#include <sys/stat.h>
@@ -284,7 +285,7 @@ static void http_reject_request_cb(struct evhttp_request* req, void*)
284285
/** Event dispatcher thread */
285286
static bool ThreadHTTP(struct event_base* base)
286287
{
287-
RenameThread("bitcoin-http");
288+
util::ThreadRename("http");
288289
LogPrint(BCLog::HTTP, "Entering http event loop\n");
289290
event_base_dispatch(base);
290291
// Event loop will be interrupted by InterruptHTTPServer()
@@ -335,9 +336,9 @@ static bool HTTPBindAddresses(struct evhttp* http)
335336
}
336337

337338
/** Simple wrapper to set thread name and run work queue */
338-
static void HTTPWorkQueueRun(WorkQueue<HTTPClosure>* queue)
339+
static void HTTPWorkQueueRun(WorkQueue<HTTPClosure>* queue, int worker_num)
339340
{
340-
RenameThread("bitcoin-httpworker");
341+
util::ThreadRename(strprintf("httpworker.%i", worker_num));
341342
queue->Run();
342343
}
343344

@@ -430,7 +431,7 @@ void StartHTTPServer()
430431
threadHTTP = std::thread(ThreadHTTP, eventBase);
431432

432433
for (int i = 0; i < rpcThreads; i++) {
433-
g_thread_http_workers.emplace_back(HTTPWorkQueueRun, workQueue);
434+
g_thread_http_workers.emplace_back(HTTPWorkQueueRun, workQueue, i);
434435
}
435436
}
436437

src/init.cpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@
4242
#include <script/sigcache.h>
4343
#include <scheduler.h>
4444
#include <shutdown.h>
45+
#include <util/threadnames.h>
4546
#include <timedata.h>
4647
#include <txdb.h>
4748
#include <txmempool.h>
@@ -208,7 +209,7 @@ void Shutdown(InitInterfaces& interfaces)
208209
/// for example if the data directory was found to be locked.
209210
/// Be sure that anything that writes files or flushes caches only does this if the respective
210211
/// module was initialized.
211-
RenameThread("bitcoin-shutoff");
212+
util::ThreadRename("shutoff");
212213
mempool.AddTransactionsUpdated(1);
213214

214215
StopHTTPRPC();
@@ -669,7 +670,7 @@ static void CleanupBlockRevFiles()
669670
static void ThreadImport(std::vector<fs::path> vImportFiles)
670671
{
671672
const CChainParams& chainparams = Params();
672-
RenameThread("bitcoin-loadblk");
673+
util::ThreadRename("loadblk");
673674
ScheduleBatchPriority();
674675

675676
{
@@ -1305,7 +1306,7 @@ bool AppInitMain(InitInterfaces& interfaces)
13051306
LogPrintf("Using %u threads for script verification\n", nScriptCheckThreads);
13061307
if (nScriptCheckThreads) {
13071308
for (int i=0; i<nScriptCheckThreads-1; i++)
1308-
threadGroup.create_thread(&ThreadScriptCheck);
1309+
threadGroup.create_thread([i]() { return ThreadScriptCheck(i); });
13091310
}
13101311

13111312
// Start the lightweight task scheduler thread

src/qt/bitcoin.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
#include <interfaces/handler.h>
3131
#include <interfaces/node.h>
3232
#include <noui.h>
33+
#include <util/threadnames.h>
3334
#include <rpc/server.h>
3435
#include <ui_interface.h>
3536
#include <uint256.h>
@@ -149,6 +150,7 @@ void BitcoinCore::initialize()
149150
try
150151
{
151152
qDebug() << __func__ << ": Running initialization in thread";
153+
util::ThreadRename("qt-init");
152154
bool rv = m_node.appInitMain();
153155
Q_EMIT initializeResult(rv);
154156
} catch (const std::exception& e) {
@@ -423,6 +425,7 @@ int GuiMain(int argc, char* argv[])
423425
std::tie(argc, argv) = winArgs.get();
424426
#endif
425427
SetupEnvironment();
428+
util::ThreadRename("main");
426429

427430
std::unique_ptr<interfaces::Node> node = interfaces::MakeNode();
428431

src/test/setup_common.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ TestingSetup::TestingSetup(const std::string& chainName) : BasicTestingSetup(cha
9494

9595
nScriptCheckThreads = 3;
9696
for (int i = 0; i < nScriptCheckThreads - 1; i++)
97-
threadGroup.create_thread(&ThreadScriptCheck);
97+
threadGroup.create_thread([i]() { return ThreadScriptCheck(i); });
9898

9999
g_banman = MakeUnique<BanMan>(GetDataDir() / "banlist.dat", nullptr, DEFAULT_MISBEHAVING_BANTIME);
100100
g_connman = MakeUnique<CConnman>(0x1337, 0x1337); // Deterministic randomness for tests.

src/util/system.cpp

Lines changed: 0 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -60,10 +60,6 @@
6060
#include <shlobj.h>
6161
#endif
6262

63-
#ifdef HAVE_SYS_PRCTL_H
64-
#include <sys/prctl.h>
65-
#endif
66-
6763
#ifdef HAVE_MALLOPT_ARENA_MAX
6864
#include <malloc.h>
6965
#endif
@@ -1137,22 +1133,6 @@ void runCommand(const std::string& strCommand)
11371133
LogPrintf("runCommand error: system(%s) returned %d\n", strCommand, nErr);
11381134
}
11391135

1140-
void RenameThread(const char* name)
1141-
{
1142-
#if defined(PR_SET_NAME)
1143-
// Only the first 15 characters are used (16 - NUL terminator)
1144-
::prctl(PR_SET_NAME, name, 0, 0, 0);
1145-
#elif (defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__DragonFly__))
1146-
pthread_set_name_np(pthread_self(), name);
1147-
1148-
#elif defined(MAC_OSX)
1149-
pthread_setname_np(name);
1150-
#else
1151-
// Prevent warnings for unused parameters...
1152-
(void)name;
1153-
#endif
1154-
}
1155-
11561136
void SetupEnvironment()
11571137
{
11581138
#ifdef HAVE_MALLOPT_ARENA_MAX

src/util/system.h

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#include <fs.h>
2121
#include <logging.h>
2222
#include <sync.h>
23+
#include <util/threadnames.h>
2324
#include <tinyformat.h>
2425
#include <util/memory.h>
2526
#include <util/time.h>
@@ -325,15 +326,12 @@ std::string HelpMessageOpt(const std::string& option, const std::string& message
325326
*/
326327
int GetNumCores();
327328

328-
void RenameThread(const char* name);
329-
330329
/**
331330
* .. and a wrapper that just calls func once
332331
*/
333332
template <typename Callable> void TraceThread(const char* name, Callable func)
334333
{
335-
std::string s = strprintf("bitcoin-%s", name);
336-
RenameThread(s.c_str());
334+
util::ThreadRename(name);
337335
try
338336
{
339337
LogPrintf("%s thread start\n", name);

src/util/threadnames.cpp

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
// Copyright (c) 2018 The Bitcoin Core developers
2+
// Distributed under the MIT software license, see the accompanying
3+
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
4+
5+
#if defined(HAVE_CONFIG_H)
6+
#include <config/bitcoin-config.h>
7+
#endif
8+
9+
#include <atomic>
10+
#include <thread>
11+
12+
#include <util/threadnames.h>
13+
14+
#ifdef HAVE_SYS_PRCTL_H
15+
#include <sys/prctl.h> // For prctl, PR_SET_NAME, PR_GET_NAME
16+
#endif
17+
18+
//! Set the thread's name at the process level. Does not affect the
19+
//! internal name.
20+
static void SetThreadName(const char* name)
21+
{
22+
#if defined(PR_SET_NAME)
23+
// Only the first 15 characters are used (16 - NUL terminator)
24+
::prctl(PR_SET_NAME, name, 0, 0, 0);
25+
#elif (defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__DragonFly__))
26+
pthread_set_name_np(pthread_self(), name);
27+
#elif defined(MAC_OSX)
28+
pthread_setname_np(name);
29+
#else
30+
// Prevent warnings for unused parameters...
31+
(void)name;
32+
#endif
33+
}
34+
35+
// If we have thread_local, just keep thread ID and name in a thread_local
36+
// global.
37+
#if defined(HAVE_THREAD_LOCAL)
38+
39+
static thread_local std::string g_thread_name;
40+
const std::string& util::ThreadGetInternalName() { return g_thread_name; }
41+
//! Set the in-memory internal name for this thread. Does not affect the process
42+
//! name.
43+
static void SetInternalName(std::string name) { g_thread_name = std::move(name); }
44+
45+
// Without thread_local available, don't handle internal name at all.
46+
#else
47+
48+
static const std::string empty_string;
49+
const std::string& util::ThreadGetInternalName() { return empty_string; }
50+
static void SetInternalName(std::string name) { }
51+
#endif
52+
53+
void util::ThreadRename(std::string&& name)
54+
{
55+
SetThreadName(("bitcoin-" + name).c_str());
56+
SetInternalName(std::move(name));
57+
}

src/util/threadnames.h

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
// Copyright (c) 2018 The Bitcoin Core developers
2+
// Distributed under the MIT software license, see the accompanying
3+
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
4+
5+
#ifndef BITCOIN_UTIL_THREADNAMES_H
6+
#define BITCOIN_UTIL_THREADNAMES_H
7+
8+
#include <string>
9+
10+
namespace util {
11+
//! Rename a thread both in terms of an internal (in-memory) name as well
12+
//! as its system thread name.
13+
void ThreadRename(std::string&&);
14+
15+
//! Get the thread's internal (in-memory) name; used e.g. for identification in
16+
//! logging.
17+
const std::string& ThreadGetInternalName();
18+
19+
} // namespace util
20+
21+
#endif // BITCOIN_UTIL_THREADNAMES_H

0 commit comments

Comments
 (0)