Inside Bitcoin
Opening the selected file…
Inside Bitcoin
Opening the selected file…
The code behind the network, with room to understand it.
Release published 2026-10-28 · Snapshot fetched 2026-11-01. Latest stable release at fetch time; development branches and Git history are excluded. Only the selected code window and visible folders load here.
1251}1252if (err.wr_ch_ != -1) popen_->stream_.err_write_ = err.wr_ch_;1253if (err.rd_ch_ != -1) popen_->stream_.err_read_ = err.rd_ch_;1254}1257#ifndef WIN321258inline void Child::execute_child() {1259int sys_ret = -1;1260auto& stream = parent_->stream_;1262try {1263if (stream.write_to_parent_ == 0)1264stream.write_to_parent_ = dup(stream.write_to_parent_);1266if (stream.err_write_ == 0 || stream.err_write_ == 1)1267stream.err_write_ = dup(stream.err_write_);1269// Make the child owned descriptors as the1270// stdin, stdout and stderr for the child process1271auto _dup2_ = [](int fd, int to_fd) {1272if (fd == to_fd) {1273// dup2 syscall does not reset the1274// CLOEXEC flag if the descriptors1275// provided to it are same.1276// But, we need to reset the CLOEXEC1277// flag as the provided descriptors1278// are now going to be the standard1279// input, output and error1280util::set_clo_on_exec(fd, false);1281} else if(fd != -1) {1282int res = dup2(fd, to_fd);1283if (res == -1) throw OSError("dup2 failed", errno);1284}1285};1287// Create the standard streams1288_dup2_(stream.read_from_parent_, 0); // Input stream1289_dup2_(stream.write_to_parent_, 1); // Output stream1290_dup2_(stream.err_write_, 2); // Error stream1292// Close the duped descriptors1293if (stream.read_from_parent_ != -1 && stream.read_from_parent_ > 2)1294subprocess_close(stream.read_from_parent_);1296if (stream.write_to_parent_ != -1 && stream.write_to_parent_ > 2)1297subprocess_close(stream.write_to_parent_);1299if (stream.err_write_ != -1 && stream.err_write_ > 2)1300subprocess_close(stream.err_write_);1302// Replace the current image with the executable1303sys_ret = execvp(parent_->exe_name_.c_str(), parent_->cargv_.data());1305if (sys_ret == -1) throw OSError("execve failed", errno);1307} catch (const OSError& exp) {1308// Just write the exception message1309// TODO: Give back stack trace ?1310std::string err_msg(exp.what());1311//ATTN: Can we do something on error here ?1312util::write_n(err_wr_pipe_, err_msg.c_str(), err_msg.length());1313}1315// Calling application would not get this1316// exit failure1317_exit (EXIT_FAILURE);1318}1319#endif1322inline void Streams::setup_comm_channels()1323{1324#ifdef WIN321325util::configure_pipe(&this->g_hChildStd_IN_Rd, &this->g_hChildStd_IN_Wr, &this->g_hChildStd_IN_Wr);1326this->input(util::file_from_handle(this->g_hChildStd_IN_Wr, "w"));1327this->write_to_child_ = subprocess_fileno(this->input());1329util::configure_pipe(&this->g_hChildStd_OUT_Rd, &this->g_hChildStd_OUT_Wr, &this->g_hChildStd_OUT_Rd);1330this->output(util::file_from_handle(this->g_hChildStd_OUT_Rd, "r"));1331this->read_from_child_ = subprocess_fileno(this->output());1333util::configure_pipe(&this->g_hChildStd_ERR_Rd, &this->g_hChildStd_ERR_Wr, &this->g_hChildStd_ERR_Rd);1334this->error(util::file_from_handle(this->g_hChildStd_ERR_Rd, "r"));1335this->err_read_ = subprocess_fileno(this->error());1336#else1338if (write_to_child_ != -1) input(fdopen(write_to_child_, "wb"));1339if (read_from_child_ != -1) output(fdopen(read_from_child_, "rb"));1340if (err_read_ != -1) error(fdopen(err_read_, "rb"));1342auto handles = {input(), output(), error()};1344for (auto& h : handles) {1345if (h == nullptr) continue;1346setvbuf(h, nullptr, _IONBF, BUFSIZ);1347}1348#endif1349}1351inline int Communication::send(const char* msg, size_t length)1352{1353if (stream_->input() == nullptr) return -1;1354return std::fwrite(msg, sizeof(char), length, stream_->input());1355}1357inline int Communication::send(const std::vector<char>& msg)1358{1359return send(msg.data(), msg.size());1360}1362inline std::pair<OutBuffer, ErrBuffer>1363Communication::communicate(const char* msg, size_t length)1364{1365// Optimization from subprocess.py1366// If we are using one pipe, or no pipe1367// at all, using select() or threads is unnecessary.1368auto hndls = {stream_->input(), stream_->output(), stream_->error()};1369int count = std::count(std::begin(hndls), std::end(hndls), nullptr);1370const int len_conv = length;1372if (count >= 2) {1373OutBuffer obuf;1374ErrBuffer ebuf;1375if (stream_->input()) {1376if (msg) {1377int wbytes = std::fwrite(msg, sizeof(char), length, stream_->input());1378if (wbytes < len_conv) {1379if (errno != EPIPE && errno != EINVAL) {1380throw OSError("fwrite error", errno);1381}1382}1383}1384// Close the input stream1385stream_->input_.reset();1386} else if (stream_->output()) {1387// Read till EOF1388// ATTN: This could be blocking, if the process1389// at the other end screws up, we get screwed as well1390obuf.add_cap(out_buf_cap_);1392int rbytes = util::read_all(1393stream_->output(),1394obuf.buf);1396if (rbytes == -1) {1397throw OSError("read to obuf failed", errno);1398}1400obuf.length = rbytes;1401// Close the output stream1402stream_->output_.reset();1404} else if (stream_->error()) {1405// Same screwness applies here as well1406ebuf.add_cap(err_buf_cap_);1408int rbytes = util::read_atmost_n(1409stream_->error(),1410ebuf.buf.data(),1411ebuf.buf.size());1413if (rbytes == -1) {1414throw OSError("read to ebuf failed", errno);1415}1417ebuf.length = rbytes;1418// Close the error stream1419stream_->error_.reset();1420}1421return std::make_pair(std::move(obuf), std::move(ebuf));1422}1424return communicate_threaded(msg, length);1425}1428inline std::pair<OutBuffer, ErrBuffer>1429Communication::communicate_threaded(const char* msg, size_t length)1430{1431OutBuffer obuf;1432ErrBuffer ebuf;1433std::future<int> out_fut, err_fut;1434const int length_conv = length;1436if (stream_->output()) {1437obuf.add_cap(out_buf_cap_);1439out_fut = std::async(std::launch::async,1440[&obuf, this] {1441return util::read_all(this->stream_->output(), obuf.buf);1442});1443}1444if (stream_->error()) {1445ebuf.add_cap(err_buf_cap_);1447err_fut = std::async(std::launch::async,1448[&ebuf, this] {1449return util::read_all(this->stream_->error(), ebuf.buf);1450});1451}1452if (stream_->input()) {1453if (msg) {1454int wbytes = std::fwrite(msg, sizeof(char), length, stream_->input());1455if (wbytes < length_conv) {1456if (errno != EPIPE && errno != EINVAL) {1457throw OSError("fwrite error", errno);1458}1459}1460}1461stream_->input_.reset();1462}1464if (out_fut.valid()) {1465int res = out_fut.get();1466if (res != -1) obuf.length = res;1467else obuf.length = 0;1468}1469if (err_fut.valid()) {1470int res = err_fut.get();1471if (res != -1) ebuf.length = res;1472else ebuf.length = 0;1473}1475return std::make_pair(std::move(obuf), std::move(ebuf));1476}1478} // end namespace detail1480}1482#endif // BITCOIN_UTIL_SUBPROCESS_H
Independent explanations by MyBitcoinExplorer. Not affiliated with or endorsed by Bitcoin Core. Guides are educational and do not replace the source or its tests.
Bitcoin Core source © its contributors, distributed under the MIT license. Original notices and bundled third-party licenses are retained in the source tree.