What changed, and why it matters
This change shortens the operating-system-visible names of Bitcoin Core's background indexer threads so they aren't cut off in Linux process tools. It does not change user-facing names, file paths, or command-line options, and it introduces no security-relevant behavior.
No security action required; this is a cosmetic/observability improvement.
Security signals we found
No strong security signals were identified.
Evidence from the diff
The commit separates the internal index name (used for logs, getindexinfo, prune locks, and disk paths) from the OS thread name passed to util::TraceThread. It shortens indexer thread names to fit within Linux’s 15-byte thread-name limit after the ‘b-’ prefix (e.g., ‘txindex’ becomes ‘txidx’, ‘coinstatsindex’ becomes ‘coinstatsidx’, and the basic block filter index becomes ‘blkfltbscidx’). An Assume(name.size() <= 13) assertion is added to ThreadRename() to guard future thread names. Public names, RPC keys, CLI options, and on-disk paths remain unchanged.
Changed components
src/index/base.cppsrc/index/base.hsrc/index/blockfilterindex.cppsrc/index/coinstatsindex.cppsrc/index/txindex.cppsrc/index/txospenderindex.cppsrc/util/threadnames.cppdoc/developer-notes.mdsrc/test/blockfilter_index_tests.cppsrc/test/util_threadnames_tests.cpptest/functional/feature_init.pyInspect captured patch +29 / −18
diff --git a/doc/developer-notes.md b/doc/developer-notes.md
index 129fdda7..962e8851 100644
--- a/doc/developer-notes.md
+++ b/doc/developer-notes.md
@@ -708,7 +708,7 @@ and its `cs_KeyStore` lock for example).
- [HTTP worker threads (`b-http.xx`)](https://doxygen.bitcoincore.org/httpserver_8cpp.html#http_pool)
: Threads to service RPC and REST requests.
-- [Indexer threads (`b-txindex`, etc)](https://doxygen.bitcoincore.org/class_base_index.html#index_sync)
+- [Indexer threads (`b-txidx`, `b-blkfltbscidx`, `b-coinstatsidx`, `b-txospenderidx`)](https://doxygen.bitcoincore.org/class_base_index.html#index_sync)
: One thread per indexer.
- [SchedulerThread (`b-scheduler`)](https://doxygen.bitcoincore.org/class_c_scheduler.html#scheduler)
diff --git a/src/index/base.cpp b/src/index/base.cpp
index bb41cc2a..906ed265 100644
--- a/src/index/base.cpp
+++ b/src/index/base.cpp
@@ -92,8 +92,8 @@ void BaseIndex::DB::WriteBestBlock(CDBBatch& batch, const CBlockLocator& locator
batch.Write(DB_BEST_BLOCK, locator);
}
-BaseIndex::BaseIndex(std::unique_ptr<interfaces::Chain> chain, std::string name)
- : m_chain{std::move(chain)}, m_name{std::move(name)} {}
+BaseIndex::BaseIndex(std::unique_ptr<interfaces::Chain> chain, std::string name, std::string thread_name)
+ : m_chain{std::move(chain)}, m_name{std::move(name)}, m_thread_name{std::move(thread_name)} {}
BaseIndex::~BaseIndex()
{
@@ -460,7 +460,7 @@ bool BaseIndex::StartBackgroundSync()
{
if (!m_init) throw std::logic_error("Error: Cannot start a non-initialized index");
- m_thread_sync = std::thread(&util::TraceThread, GetName(), [this] { Sync(); });
+ m_thread_sync = std::thread(&util::TraceThread, m_thread_name, [this] { Sync(); });
return true;
}
diff --git a/src/index/base.h b/src/index/base.h
index 761b6f56..6d7e86ec 100644
--- a/src/index/base.h
+++ b/src/index/base.h
@@ -117,6 +117,7 @@ protected:
std::unique_ptr<interfaces::Chain> m_chain;
Chainstate* m_chainstate{nullptr};
const std::string m_name;
+ const std::string m_thread_name;
void BlockConnected(const kernel::ChainstateRole& role, const std::shared_ptr<const CBlock>& block, const CBlockIndex* pindex) override;
@@ -141,7 +142,7 @@ protected:
void SetBestBlockIndex(const CBlockIndex* block);
public:
- BaseIndex(std::unique_ptr<interfaces::Chain> chain, std::string name);
+ BaseIndex(std::unique_ptr<interfaces::Chain> chain, std::string name, std::string thread_name);
/// Destructor interrupts sync thread if running and blocks until it exits.
virtual ~BaseIndex();
diff --git a/src/index/blockfilterindex.cpp b/src/index/blockfilterindex.cpp
index d4fd7025..5c4a1813 100644
--- a/src/index/blockfilterindex.cpp
+++ b/src/index/blockfilterindex.cpp
@@ -61,6 +61,15 @@ constexpr size_t CF_HEADERS_CACHE_MAX_SZ{2000};
namespace {
+std::string BlockFilterThreadName(BlockFilterType filter_type)
+{
+ switch (filter_type) {
+ case BlockFilterType::BASIC: return "blkfltbscidx";
+ case BlockFilterType::INVALID: return "";
+ } // no default case, so the compiler can warn about missing cases
+ assert(false);
+}
+
struct DBVal {
uint256 hash;
uint256 header;
@@ -75,7 +84,7 @@ static std::map<BlockFilterType, BlockFilterIndex> g_filter_indexes;
BlockFilterIndex::BlockFilterIndex(std::unique_ptr<interfaces::Chain> chain, BlockFilterType filter_type,
size_t n_cache_size, bool f_memory, bool f_wipe)
- : BaseIndex(std::move(chain), BlockFilterTypeName(filter_type) + " block filter index")
+ : BaseIndex(std::move(chain), BlockFilterTypeName(filter_type) + " block filter index", BlockFilterThreadName(filter_type))
, m_filter_type(filter_type)
{
const std::string& filter_name = BlockFilterTypeName(filter_type);
diff --git a/src/index/coinstatsindex.cpp b/src/index/coinstatsindex.cpp
index 80a6d8df..204f4341 100644
--- a/src/index/coinstatsindex.cpp
+++ b/src/index/coinstatsindex.cpp
@@ -87,7 +87,7 @@ struct DBVal {
std::unique_ptr<CoinStatsIndex> g_coin_stats_index;
CoinStatsIndex::CoinStatsIndex(std::unique_ptr<interfaces::Chain> chain, size_t n_cache_size, bool f_memory, bool f_wipe)
- : BaseIndex(std::move(chain), "coinstatsindex")
+ : BaseIndex(std::move(chain), "coinstatsindex", "coinstatsidx")
{
// An earlier version of the index used "indexes/coinstats" but it contained
// a bug and is superseded by a fixed version at "indexes/coinstatsindex".
diff --git a/src/index/txindex.cpp b/src/index/txindex.cpp
index 4b0c8287..5e71e6bb 100644
--- a/src/index/txindex.cpp
+++ b/src/index/txindex.cpp
@@ -66,7 +66,7 @@ void TxIndex::DB::WriteTxs(const std::vector<std::pair<Txid, CDiskTxPos>>& v_pos
}
TxIndex::TxIndex(std::unique_ptr<interfaces::Chain> chain, size_t n_cache_size, bool f_memory, bool f_wipe)
- : BaseIndex(std::move(chain), "txindex"), m_db(std::make_unique<TxIndex::DB>(n_cache_size, f_memory, f_wipe))
+ : BaseIndex(std::move(chain), "txindex", "txidx"), m_db(std::make_unique<TxIndex::DB>(n_cache_size, f_memory, f_wipe))
{}
TxIndex::~TxIndex() = default;
diff --git a/src/index/txospenderindex.cpp b/src/index/txospenderindex.cpp
index f0d559a9..3d7b56b6 100644
--- a/src/index/txospenderindex.cpp
+++ b/src/index/txospenderindex.cpp
@@ -60,7 +60,7 @@ struct DBKey {
};
TxoSpenderIndex::TxoSpenderIndex(std::unique_ptr<interfaces::Chain> chain, size_t n_cache_size, bool f_memory, bool f_wipe)
- : BaseIndex(std::move(chain), "txospenderindex"), m_db{std::make_unique<DB>(gArgs.GetDataDirNet() / "indexes" / "txospenderindex" / "db", n_cache_size, f_memory, f_wipe)}
+ : BaseIndex(std::move(chain), "txospenderindex", "txospenderidx"), m_db{std::make_unique<DB>(gArgs.GetDataDirNet() / "indexes" / "txospenderindex" / "db", n_cache_size, f_memory, f_wipe)}
{
if (!m_db->Read("siphash_key", m_siphash_key)) {
FastRandomContext rng(false);
diff --git a/src/test/blockfilter_index_tests.cpp b/src/test/blockfilter_index_tests.cpp
index a48a355d..6e035c56 100644
--- a/src/test/blockfilter_index_tests.cpp
+++ b/src/test/blockfilter_index_tests.cpp
@@ -338,9 +338,8 @@ private:
int m_blocking_height;
public:
- explicit IndexReorgCrash(std::unique_ptr<interfaces::Chain> chain, std::shared_future<void> blocker,
- int blocking_height, FakeNodeClock& clock)
- : BaseIndex(std::move(chain), "test index"), m_clock(clock), m_blocker(blocker), m_blocking_height(blocking_height)
+ explicit IndexReorgCrash(std::unique_ptr<interfaces::Chain> chain, std::shared_future<void> blocker, int blocking_height, FakeNodeClock& clock)
+ : BaseIndex(std::move(chain), "test index", "testidx"), m_clock(clock), m_blocker(blocker), m_blocking_height(blocking_height)
{
const fs::path path = gArgs.GetDataDirNet() / "index";
fs::create_directories(path);
diff --git a/src/test/util_threadnames_tests.cpp b/src/test/util_threadnames_tests.cpp
index f22eb12d..e10553b8 100644
--- a/src/test/util_threadnames_tests.cpp
+++ b/src/test/util_threadnames_tests.cpp
@@ -17,7 +17,7 @@ using util::ToString;
BOOST_AUTO_TEST_SUITE(util_threadnames_tests)
-const std::string TEST_THREAD_NAME_BASE = "test_thread.";
+const std::string TEST_THREAD_NAME_BASE = "test_thrd.";
/**
* Run a bunch of threads to all call util::ThreadRename.
@@ -56,7 +56,7 @@ BOOST_AUTO_TEST_CASE(util_threadnames_test_rename_threaded)
BOOST_CHECK_EQUAL(names.size(), 100U);
- // Names "test_thread.[n]" should exist for n = [0, 99]
+ // Names "test_thrd.[n]" should exist for n = [0, 99]
for (int i = 0; i < 100; ++i) {
BOOST_CHECK(names.contains(TEST_THREAD_NAME_BASE + ToString(i)));
}
diff --git a/src/util/threadnames.cpp b/src/util/threadnames.cpp
index 0615b331..a9a3649b 100644
--- a/src/util/threadnames.cpp
+++ b/src/util/threadnames.cpp
@@ -3,6 +3,7 @@
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <util/threadnames.h>
+#include <util/check.h>
#include <algorithm>
#include <cstring>
@@ -53,6 +54,7 @@ static void SetInternalName(const std::string& name)
void util::ThreadRename(const std::string& name)
{
+ Assume(name.size() <= 13); // Linux keeps 15 bytes
SetThreadName(("b-" + name).c_str());
SetInternalName(name);
}
diff --git a/test/functional/feature_init.py b/test/functional/feature_init.py
index 259e07b1..526fe63a 100755
--- a/test/functional/feature_init.py
+++ b/test/functional/feature_init.py
@@ -77,10 +77,10 @@ class InitTest(BitcoinTestFramework):
b'net thread start',
b'addcon thread start',
b'initload thread start',
- b'txindex thread start',
- b'block filter index thread start',
- b'coinstatsindex thread start',
- b'txospenderindex thread start',
+ b'txidx thread start',
+ b'blkfltbscidx thread start',
+ b'coinstatsidx thread start',
+ b'txospenderidx thread start',
b'msghand thread start',
b'net thread start',
b'addcon thread start',
Why this scored 15/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.