Worker thread shares same name with event loop thread creating confusion when inspecting in GDB #248

issue Eunovo openend this issue on March 10, 2026
  1. Eunovo commented at 12:32 pm on March 10, 2026: contributor

    In the image obtained from running bitcoin-core’s interface_ipc_mining test below, there are two “b-capnp-loop” threads: only one (Thread ID 11) is the actual worker thread calling createNewBlock().

    This creates confusion for the developer trying to find the right thread to inspect.

    I took a quick stab at this and tried to set the name of the newly created thread in ProxyServer<ThreadMap>::makeThread, but it didn’t seem to work.

    You can reproduce with this diff applied to bitcoin-core and using GDB to inspect the running threads.

     0diff --git a/src/interfaces/mining.h b/src/interfaces/mining.h
     1index f4c42e204a..bbef70196b 100644
     2--- a/src/interfaces/mining.h
     3+++ b/src/interfaces/mining.h
     4@@ -139,6 +139,13 @@ public:
     5      */
     6     virtual void interrupt() = 0;
     7 
     8+    /**
     9+     * Sets the debug mining flag.
    10+     *
    11+     * [@param](/bitcoin-core-multiprocess/contributor/param/)[in] debug_mining whether to enable debug mining mode
    12+     */
    13+    virtual void setDebugMining(bool debug_mining) = 0;
    14+
    15     /**
    16      * Checks if a given block is valid.
    17      *
    18diff --git a/src/ipc/capnp/mining.capnp b/src/ipc/capnp/mining.capnp
    19index 64cad4d49f..38a1758f61 100644
    20--- a/src/ipc/capnp/mining.capnp
    21+++ b/src/ipc/capnp/mining.capnp
    22@@ -25,6 +25,7 @@ interface Mining $Proxy.wrap("interfaces::Mining") {
    23     createNewBlock [@4](/bitcoin-core-multiprocess/contributor/4/) (context :Proxy.Context, options: BlockCreateOptions, cooldown: Bool = true) -> (result: BlockTemplate);
    24     checkBlock [@5](/bitcoin-core-multiprocess/contributor/5/) (context :Proxy.Context, block: Data, options: BlockCheckOptions) -> (reason: Text, debug: Text, result: Bool);
    25     interrupt [@6](/bitcoin-core-multiprocess/contributor/6/) () -> ();
    26+    setDebugMining [@7](/bitcoin-core-multiprocess/contributor/7/) (debugMining: Bool) -> ();
    27 }
    28 
    29 interface BlockTemplate $Proxy.wrap("interfaces::BlockTemplate") {
    30diff --git a/src/node/interfaces.cpp b/src/node/interfaces.cpp
    31index 84fd5bb794..e83e7ea003 100644
    32--- a/src/node/interfaces.cpp
    33+++ b/src/node/interfaces.cpp
    34@@ -959,6 +959,9 @@ public:
    35 
    36     std::unique_ptr<BlockTemplate> createNewBlock(const BlockCreateOptions& options, bool cooldown) override
    37     {
    38+        if (m_debug_mining) {
    39+            while (true) {} //DEBUG
    40+        }
    41         // Reject too-small values instead of clamping so callers don't silently
    42         // end up mining with different options than requested. This matches the
    43         // behavior of the `-blockreservedweight` startup option, which rejects
    44@@ -999,6 +1002,11 @@ public:
    45         InterruptWait(notifications(), m_interrupt_mining);
    46     }
    47 
    48+    void setDebugMining(bool debug_mining) override
    49+    {
    50+        m_debug_mining = debug_mining;
    51+    }
    52+
    53     bool checkBlock(const CBlock& block, const node::BlockCheckOptions& options, std::string& reason, std::string& debug) override
    54     {
    55         LOCK(chainman().GetMutex());
    56@@ -1013,6 +1021,7 @@ public:
    57     KernelNotifications& notifications() { return *Assert(m_node.notifications); }
    58     // Treat as if guarded by notifications().m_tip_block_mutex
    59     bool m_interrupt_mining{false};
    60+    bool m_debug_mining{false};
    61     NodeContext& m_node;
    62 };
    63 } // namespace
    64diff --git a/test/functional/test_framework/ipc_util.py b/test/functional/test_framework/ipc_util.py
    65index 11497463eb..1469294b63 100644
    66--- a/test/functional/test_framework/ipc_util.py
    67+++ b/test/functional/test_framework/ipc_util.py
    68@@ -108,6 +108,8 @@ async def make_capnp_init_ctx(self):
    69 
    70 async def mining_create_block_template(mining, stack, ctx, opts):
    71     """Call mining.createNewBlock() and return template, then call template.destroy() when stack exits."""
    72+    await mining.setDebugMining(True)  # Block createNewBlock() infinitely
    73+    import pdb; pdb.set_trace()
    74     response = await mining.createNewBlock(ctx, opts)
    75     if not response._has("result"):
    76         return None
    
  2. ryanofsky commented at 1:39 am on March 12, 2026: collaborator

    I took a quick stab at this and tried to set the name of the newly created thread in ProxyServer<ThreadMap>::makeThread, but it didn’t seem to work.

    That’s surprising. But one problem might be that the thread name passed passed to the OS is too long. I believe the name passed includes the exe name + thread name from the calling process. Might make sense to split it up or add truncation if that is the problem

  3. Eunovo commented at 10:54 am on March 12, 2026: contributor

    I believe the name passed includes the exe name + thread name from the calling process. Might make sense to split it up or add truncation if that is the problem

    I had the same thought, and I believe I tried shorter names as well, but the name of the worker thread remained unchanged. I can double-check this later to confirm.


github-metadata-mirror

This is a metadata mirror of the GitHub repository bitcoin-core/libmultiprocess. This site is not affiliated with GitHub. Content is generated from a GitHub metadata backup.
generated: 2026-03-29 21:30 UTC

This site is hosted by @0xB10C
More mirrored repositories can be found on mirror.b10c.me