LCOV - code coverage report
Current view: top level - src/ipc - interfaces.cpp (source / functions) Coverage Total Hit
Test: total_coverage.info Lines: 0.0 % 61 0
Test Date: 2025-08-25 05:11:47 Functions: 0.0 % 12 0
Branches: 0.0 % 44 0

             Branch data     Line data    Source code
       1                 :             : // Copyright (c) 2021-2022 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                 :             : #include <common/args.h>
       6                 :             : #include <common/system.h>
       7                 :             : #include <interfaces/init.h>
       8                 :             : #include <interfaces/ipc.h>
       9                 :             : #include <ipc/capnp/protocol.h>
      10                 :             : #include <ipc/process.h>
      11                 :             : #include <ipc/protocol.h>
      12                 :             : #include <logging.h>
      13                 :             : #include <tinyformat.h>
      14                 :             : #include <util/fs.h>
      15                 :             : 
      16                 :             : #include <csignal>
      17                 :             : #include <cstdio>
      18                 :             : #include <cstdlib>
      19                 :             : #include <cstring>
      20                 :             : #include <functional>
      21                 :             : #include <memory>
      22                 :             : #include <stdexcept>
      23                 :             : #include <string>
      24                 :             : #include <unistd.h>
      25                 :             : #include <utility>
      26                 :             : #include <vector>
      27                 :             : 
      28                 :             : namespace ipc {
      29                 :             : namespace {
      30                 :             : #ifndef WIN32
      31                 :             : std::string g_ignore_ctrl_c;
      32                 :             : 
      33                 :           0 : void HandleCtrlC(int)
      34                 :             : {
      35                 :             :     // (void)! needed to suppress -Wunused-result warning from GCC
      36         [ #  # ]:           0 :     (void)!write(STDOUT_FILENO, g_ignore_ctrl_c.data(), g_ignore_ctrl_c.size());
      37                 :           0 : }
      38                 :             : #endif
      39                 :             : 
      40                 :           0 : void IgnoreCtrlC(std::string message)
      41                 :             : {
      42                 :             : #ifndef WIN32
      43                 :           0 :     g_ignore_ctrl_c = std::move(message);
      44                 :           0 :     struct sigaction sa{};
      45                 :           0 :     sa.sa_handler = HandleCtrlC;
      46                 :           0 :     sigemptyset(&sa.sa_mask);
      47                 :           0 :     sa.sa_flags = SA_RESTART;
      48                 :           0 :     sigaction(SIGINT, &sa, nullptr);
      49                 :             : #endif
      50                 :           0 : }
      51                 :             : 
      52                 :             : class IpcImpl : public interfaces::Ipc
      53                 :             : {
      54                 :             : public:
      55                 :           0 :     IpcImpl(const char* exe_name, const char* process_argv0, interfaces::Init& init)
      56                 :           0 :         : m_exe_name(exe_name), m_process_argv0(process_argv0), m_init(init),
      57   [ #  #  #  # ]:           0 :           m_protocol(ipc::capnp::MakeCapnpProtocol()), m_process(ipc::MakeProcess())
      58                 :             :     {
      59                 :           0 :     }
      60                 :           0 :     std::unique_ptr<interfaces::Init> spawnProcess(const char* new_exe_name) override
      61                 :             :     {
      62                 :           0 :         int pid;
      63   [ #  #  #  # ]:           0 :         int fd = m_process->spawn(new_exe_name, m_process_argv0, pid);
      64         [ #  # ]:           0 :         LogDebug(::BCLog::IPC, "Process %s pid %i launched\n", new_exe_name, pid);
      65                 :           0 :         auto init = m_protocol->connect(fd, m_exe_name);
      66   [ #  #  #  # ]:           0 :         Ipc::addCleanup(*init, [this, new_exe_name, pid] {
      67                 :           0 :             int status = m_process->waitSpawned(pid);
      68         [ #  # ]:           0 :             LogDebug(::BCLog::IPC, "Process %s pid %i exited with status %i\n", new_exe_name, pid, status);
      69                 :           0 :         });
      70                 :           0 :         return init;
      71                 :           0 :     }
      72                 :           0 :     bool startSpawnedProcess(int argc, char* argv[], int& exit_status) override
      73                 :             :     {
      74                 :           0 :         exit_status = EXIT_FAILURE;
      75                 :           0 :         int32_t fd = -1;
      76         [ #  # ]:           0 :         if (!m_process->checkSpawned(argc, argv, fd)) {
      77                 :             :             return false;
      78                 :             :         }
      79                 :           0 :         IgnoreCtrlC(strprintf("[%s] SIGINT received — waiting for parent to shut down.\n", m_exe_name));
      80         [ #  # ]:           0 :         m_protocol->serve(fd, m_exe_name, m_init);
      81                 :           0 :         exit_status = EXIT_SUCCESS;
      82                 :           0 :         return true;
      83                 :             :     }
      84                 :           0 :     std::unique_ptr<interfaces::Init> connectAddress(std::string& address) override
      85                 :             :     {
      86   [ #  #  #  # ]:           0 :         if (address.empty() || address == "0") return nullptr;
      87                 :           0 :         int fd;
      88         [ #  # ]:           0 :         if (address == "auto") {
      89                 :             :             // Treat "auto" the same as "unix" except don't treat it an as error
      90                 :             :             // if the connection is not accepted. Just return null so the caller
      91                 :             :             // can work offline without a connection, or spawn a new
      92                 :             :             // bitcoin-node process and connect to it.
      93                 :           0 :             address = "unix";
      94                 :           0 :             try {
      95   [ #  #  #  # ]:           0 :                 fd = m_process->connect(gArgs.GetDataDirNet(), "bitcoin-node", address);
      96         [ -  - ]:           0 :             } catch (const std::system_error& e) {
      97                 :             :                 // If connection type is auto and socket path isn't accepting connections, or doesn't exist, catch the error and return null;
      98   [ -  -  -  - ]:           0 :                 if (e.code() == std::errc::connection_refused || e.code() == std::errc::no_such_file_or_directory) {
      99                 :           0 :                     return nullptr;
     100                 :             :                 }
     101                 :           0 :                 throw;
     102                 :           0 :             }
     103                 :             :         } else {
     104         [ #  # ]:           0 :             fd = m_process->connect(gArgs.GetDataDirNet(), "bitcoin-node", address);
     105                 :             :         }
     106                 :           0 :         return m_protocol->connect(fd, m_exe_name);
     107                 :             :     }
     108                 :           0 :     void listenAddress(std::string& address) override
     109                 :             :     {
     110         [ #  # ]:           0 :         int fd = m_process->bind(gArgs.GetDataDirNet(), m_exe_name, address);
     111                 :           0 :         m_protocol->listen(fd, m_exe_name, m_init);
     112                 :           0 :     }
     113                 :           0 :     void disconnectIncoming() override
     114                 :             :     {
     115                 :           0 :         m_protocol->disconnectIncoming();
     116                 :           0 :     }
     117                 :           0 :     void addCleanup(std::type_index type, void* iface, std::function<void()> cleanup) override
     118                 :             :     {
     119         [ #  # ]:           0 :         m_protocol->addCleanup(type, iface, std::move(cleanup));
     120                 :           0 :     }
     121                 :           0 :     Context& context() override { return m_protocol->context(); }
     122                 :             :     const char* m_exe_name;
     123                 :             :     const char* m_process_argv0;
     124                 :             :     interfaces::Init& m_init;
     125                 :             :     std::unique_ptr<Protocol> m_protocol;
     126                 :             :     std::unique_ptr<Process> m_process;
     127                 :             : };
     128                 :             : } // namespace
     129                 :             : } // namespace ipc
     130                 :             : 
     131                 :             : namespace interfaces {
     132                 :           0 : std::unique_ptr<Ipc> MakeIpc(const char* exe_name, const char* process_argv0, Init& init)
     133                 :             : {
     134                 :           0 :     return std::make_unique<ipc::IpcImpl>(exe_name, process_argv0, init);
     135                 :             : }
     136                 :             : } // namespace interfaces
        

Generated by: LCOV version 2.0-1