Bitcoin Core 29.99.0
P2P Digital Currency
util.cpp
Go to the documentation of this file.
1// Copyright (c) 2018-2019 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 <mp/config.h>
6#include <mp/util.h>
7
8#include <errno.h>
9#include <kj/common.h>
10#include <kj/string-tree.h>
11#include <pthread.h>
12#include <sstream>
13#include <stdio.h>
14#include <string>
15#include <sys/resource.h>
16#include <sys/socket.h>
17#include <sys/wait.h>
18#include <system_error>
19#include <unistd.h>
20#include <utility>
21#include <vector>
22
23#ifdef __linux__
24#include <sys/syscall.h>
25#endif
26
27#ifdef HAVE_PTHREAD_GETTHREADID_NP
28#include <pthread_np.h>
29#endif // HAVE_PTHREAD_GETTHREADID_NP
30
31namespace mp {
32namespace {
33
35size_t MaxFd()
36{
37 struct rlimit nofile;
38 if (getrlimit(RLIMIT_NOFILE, &nofile) == 0) {
39 return nofile.rlim_cur - 1;
40 } else {
41 return 1023;
42 }
43}
44
45} // namespace
46
47std::string ThreadName(const char* exe_name)
48{
49 char thread_name[16] = {0};
50#ifdef HAVE_PTHREAD_GETNAME_NP
51 pthread_getname_np(pthread_self(), thread_name, sizeof(thread_name));
52#endif // HAVE_PTHREAD_GETNAME_NP
53
54 std::ostringstream buffer;
55 buffer << (exe_name ? exe_name : "") << "-" << getpid() << "/";
56
57 if (thread_name[0] != '\0') {
58 buffer << thread_name << "-";
59 }
60
61 // Prefer platform specific thread ids over the standard C++11 ones because
62 // the former are shorter and are the same as what gdb prints "LWP ...".
63#ifdef __linux__
64 buffer << syscall(SYS_gettid);
65#elif defined(HAVE_PTHREAD_THREADID_NP)
66 uint64_t tid = 0;
67 pthread_threadid_np(NULL, &tid);
68 buffer << tid;
69#elif defined(HAVE_PTHREAD_GETTHREADID_NP)
70 buffer << pthread_getthreadid_np();
71#else
72 buffer << std::this_thread::get_id();
73#endif
74
75 return std::move(buffer).str();
76}
77
78std::string LogEscape(const kj::StringTree& string)
79{
80 const int MAX_SIZE = 1000;
81 std::string result;
82 string.visit([&](const kj::ArrayPtr<const char>& piece) {
83 if (result.size() > MAX_SIZE) return;
84 for (const char c : piece) {
85 if (c == '\\') {
86 result.append("\\\\");
87 } else if (c < 0x20 || c > 0x7e) {
88 char escape[4];
89 snprintf(escape, 4, "\\%02x", c);
90 result.append(escape);
91 } else {
92 result.push_back(c);
93 }
94 if (result.size() > MAX_SIZE) {
95 result += "...";
96 break;
97 }
98 }
99 });
100 return result;
101}
102
103int SpawnProcess(int& pid, FdToArgsFn&& fd_to_args)
104{
105 int fds[2];
106 if (socketpair(AF_UNIX, SOCK_STREAM, 0, fds) != 0) {
107 throw std::system_error(errno, std::system_category(), "socketpair");
108 }
109
110 pid = fork();
111 if (pid == -1) {
112 throw std::system_error(errno, std::system_category(), "fork");
113 }
114 // Parent process closes the descriptor for socket 0, child closes the descriptor for socket 1.
115 if (close(fds[pid ? 0 : 1]) != 0) {
116 throw std::system_error(errno, std::system_category(), "close");
117 }
118 if (!pid) {
119 // Child process must close all potentially open descriptors, except socket 0.
120 const int maxFd = MaxFd();
121 for (int fd = 3; fd < maxFd; ++fd) {
122 if (fd != fds[0]) {
123 close(fd);
124 }
125 }
126 ExecProcess(fd_to_args(fds[0]));
127 }
128 return fds[1];
129}
130
131void ExecProcess(const std::vector<std::string>& args)
132{
133 std::vector<char*> argv;
134 argv.reserve(args.size());
135 for (const auto& arg : args) {
136 argv.push_back(const_cast<char*>(arg.c_str()));
137 }
138 argv.push_back(nullptr);
139 if (execvp(argv[0], argv.data()) != 0) {
140 perror("execlp failed");
141 _exit(1);
142 }
143}
144
145int WaitProcess(int pid)
146{
147 int status;
148 if (::waitpid(pid, &status, 0 /* options */) != pid) {
149 throw std::system_error(errno, std::system_category(), "waitpid");
150 }
151 return status;
152}
153
154} // namespace mp
ArgsManager & args
Definition: bitcoind.cpp:277
Functions to serialize / deserialize common bitcoin types.
Definition: common-types.h:57
int WaitProcess(int pid)
Wait for a process to exit and return its exit code.
Definition: util.cpp:145
std::string ThreadName(const char *exe_name)
Format current thread name as "{exe_name}-{$pid}/{thread_name}-{$tid}".
Definition: util.cpp:47
int SpawnProcess(int &pid, FdToArgsFn &&fd_to_args)
Spawn a new process that communicates with the current process over a socket pair.
Definition: util.cpp:103
std::string LogEscape(const kj::StringTree &string)
Escape binary string for use in log so it doesn't trigger unicode decode errors in python unit tests.
Definition: util.cpp:78
std::function< std::vector< std::string >(int fd)> FdToArgsFn
Callback type used by SpawnProcess below.
Definition: util.h:197
void ExecProcess(const std::vector< std::string > &args)
Call execvp with vector args.
Definition: util.cpp:131
static constexpr uint64_t MAX_SIZE
The maximum size of a serialized object in bytes or number of elements (for eg vectors) when the size...
Definition: serialize.h:32
for(const CTxIn &txin :tx.vin)
Definition: validation.cpp:407