Bitcoin Core  27.99.0
P2P Digital Currency
protocol.cpp
Go to the documentation of this file.
1 // Copyright (c) 2021 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 <interfaces/init.h>
6 #include <ipc/capnp/context.h>
7 #include <ipc/capnp/init.capnp.h>
8 #include <ipc/capnp/init.capnp.proxy.h>
9 #include <ipc/capnp/protocol.h>
10 #include <ipc/exception.h>
11 #include <ipc/protocol.h>
12 #include <kj/async.h>
13 #include <logging.h>
14 #include <mp/proxy-io.h>
15 #include <mp/proxy-types.h>
16 #include <mp/util.h>
17 #include <util/threadnames.h>
18 
19 #include <assert.h>
20 #include <errno.h>
21 #include <future>
22 #include <memory>
23 #include <mutex>
24 #include <optional>
25 #include <string>
26 #include <thread>
27 
28 namespace ipc {
29 namespace capnp {
30 namespace {
31 void IpcLogFn(bool raise, std::string message)
32 {
33  LogPrint(BCLog::IPC, "%s\n", message);
34  if (raise) throw Exception(message);
35 }
36 
37 class CapnpProtocol : public Protocol
38 {
39 public:
40  ~CapnpProtocol() noexcept(true)
41  {
42  if (m_loop) {
43  std::unique_lock<std::mutex> lock(m_loop->m_mutex);
44  m_loop->removeClient(lock);
45  }
46  if (m_loop_thread.joinable()) m_loop_thread.join();
47  assert(!m_loop);
48  };
49  std::unique_ptr<interfaces::Init> connect(int fd, const char* exe_name) override
50  {
51  startLoop(exe_name);
52  return mp::ConnectStream<messages::Init>(*m_loop, fd);
53  }
54  void serve(int fd, const char* exe_name, interfaces::Init& init) override
55  {
56  assert(!m_loop);
57  mp::g_thread_context.thread_name = mp::ThreadName(exe_name);
58  m_loop.emplace(exe_name, &IpcLogFn, &m_context);
59  mp::ServeStream<messages::Init>(*m_loop, fd, init);
60  m_loop->loop();
61  m_loop.reset();
62  }
63  void addCleanup(std::type_index type, void* iface, std::function<void()> cleanup) override
64  {
65  mp::ProxyTypeRegister::types().at(type)(iface).cleanup.emplace_back(std::move(cleanup));
66  }
67  Context& context() override { return m_context; }
68  void startLoop(const char* exe_name)
69  {
70  if (m_loop) return;
71  std::promise<void> promise;
72  m_loop_thread = std::thread([&] {
73  util::ThreadRename("capnp-loop");
74  m_loop.emplace(exe_name, &IpcLogFn, &m_context);
75  {
76  std::unique_lock<std::mutex> lock(m_loop->m_mutex);
77  m_loop->addClient(lock);
78  }
79  promise.set_value();
80  m_loop->loop();
81  m_loop.reset();
82  });
83  promise.get_future().wait();
84  }
85  Context m_context;
86  std::thread m_loop_thread;
87  std::optional<mp::EventLoop> m_loop;
88 };
89 } // namespace
90 
91 std::unique_ptr<Protocol> MakeCapnpProtocol() { return std::make_unique<CapnpProtocol>(); }
92 } // namespace capnp
93 } // namespace ipc
Initial interface created when a process is first started, and used to give and get access to other i...
Definition: init.h:30
std::thread m_loop_thread
Definition: protocol.cpp:86
std::optional< mp::EventLoop > m_loop
Definition: protocol.cpp:87
Context m_context
Definition: protocol.cpp:85
#define LogPrint(category,...)
Definition: logging.h:263
@ IPC
Definition: logging.h:64
std::unique_ptr< Protocol > MakeCapnpProtocol()
Definition: protocol.cpp:91
Definition: ipc.h:12
void ThreadRename(std::string &&)
Rename a thread both in terms of an internal (in-memory) name as well as its system thread name.
Definition: threadnames.cpp:59
assert(!tx.IsCoinBase())