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.
751// Lets call it parent even though752// technically a bit incorrect753Popen* parent_ = nullptr;754int err_wr_pipe_ = -1;755};756#endif758// Fwd Decl.759class Streams;761/*!762* A helper class to Streams.763* This takes care of management of communicating764* with the child process with the means of the correct765* file descriptor.766*/767class Communication768{769public:770Communication(Streams* stream): stream_(stream)771{}772Communication(const Communication&) = delete;773Communication& operator=(const Communication&) = delete;774Communication(Communication&&) = default;775Communication& operator=(Communication&&) = default;776public:777int send(const char* msg, size_t length);778int send(const std::vector<char>& msg);780std::pair<OutBuffer, ErrBuffer> communicate(const char* msg, size_t length);781std::pair<OutBuffer, ErrBuffer> communicate(const std::vector<char>& msg)782{ return communicate(msg.data(), msg.size()); }784void set_out_buf_cap(size_t cap) { out_buf_cap_ = cap; }785void set_err_buf_cap(size_t cap) { err_buf_cap_ = cap; }787private:788std::pair<OutBuffer, ErrBuffer> communicate_threaded(789const char* msg, size_t length);791private:792Streams* stream_;793size_t out_buf_cap_ = DEFAULT_BUF_CAP_BYTES;794size_t err_buf_cap_ = DEFAULT_BUF_CAP_BYTES;795};799/*!800* This is a helper class to Popen.801* It takes care of management of all the file descriptors802* and file pointers.803* It dispatches of the communication aspects to the804* Communication class.805* Read through the data members to understand about the806* various file descriptors used.807*/808class Streams809{810public:811Streams():comm_(this) {}812Streams(const Streams&) = delete;813Streams& operator=(const Streams&) = delete;814Streams(Streams&&) = default;815Streams& operator=(Streams&&) = default;817public:818void setup_comm_channels();820void cleanup_fds()821{822if (write_to_child_ != -1 && read_from_parent_ != -1) {823subprocess_close(write_to_child_);824}825if (write_to_parent_ != -1 && read_from_child_ != -1) {826subprocess_close(read_from_child_);827}828if (err_write_ != -1 && err_read_ != -1) {829subprocess_close(err_read_);830}831}833void close_parent_fds()834{835if (write_to_child_ != -1) subprocess_close(write_to_child_);836if (read_from_child_ != -1) subprocess_close(read_from_child_);837if (err_read_ != -1) subprocess_close(err_read_);838}840void close_child_fds()841{842if (write_to_parent_ != -1) subprocess_close(write_to_parent_);843if (read_from_parent_ != -1) subprocess_close(read_from_parent_);844if (err_write_ != -1) subprocess_close(err_write_);845}847FILE* input() { return input_.get(); }848FILE* output() { return output_.get(); }849FILE* error() { return error_.get(); }851void input(FILE* fp) { input_.reset(fp, fclose); }852void output(FILE* fp) { output_.reset(fp, fclose); }853void error(FILE* fp) { error_.reset(fp, fclose); }855void set_out_buf_cap(size_t cap) { comm_.set_out_buf_cap(cap); }856void set_err_buf_cap(size_t cap) { comm_.set_err_buf_cap(cap); }858public: /* Communication forwarding API's */859int send(const char* msg, size_t length)860{ return comm_.send(msg, length); }862int send(const std::vector<char>& msg)863{ return comm_.send(msg); }865std::pair<OutBuffer, ErrBuffer> communicate(const char* msg, size_t length)866{ return comm_.communicate(msg, length); }868std::pair<OutBuffer, ErrBuffer> communicate(const std::vector<char>& msg)869{ return comm_.communicate(msg); }872public:// Yes they are public874std::shared_ptr<FILE> input_ = nullptr;875std::shared_ptr<FILE> output_ = nullptr;876std::shared_ptr<FILE> error_ = nullptr;878#ifdef WIN32879HANDLE g_hChildStd_IN_Rd = nullptr;880HANDLE g_hChildStd_IN_Wr = nullptr;881HANDLE g_hChildStd_OUT_Rd = nullptr;882HANDLE g_hChildStd_OUT_Wr = nullptr;883HANDLE g_hChildStd_ERR_Rd = nullptr;884HANDLE g_hChildStd_ERR_Wr = nullptr;885#endif887// Pipes for communicating with child889// Emulates stdin890int write_to_child_ = -1; // Parent owned descriptor891int read_from_parent_ = -1; // Child owned descriptor893// Emulates stdout894int write_to_parent_ = -1; // Child owned descriptor895int read_from_child_ = -1; // Parent owned descriptor897// Emulates stderr898int err_write_ = -1; // Write error to parent (Child owned)899int err_read_ = -1; // Read error from child (Parent owned)901private:902Communication comm_;903};905} // end namespace detail909/*!910* class: Popen911* This is the single most important class in the whole library912* and glues together all the helper classes to provide a common913* interface to the client.914*915* API's provided by the class:916* Popen({"cmd"}, output{..}, error{..}, ....)917* Command provided as a sequence.918* wait() - Wait for the child to exit.919* retcode() - The return code of the exited child.920* send(...) - Send input to the input channel of the child.921* communicate(...) - Get the output/error from the child and close the channels922* from the parent side.923*/924class Popen925{926public:927friend struct detail::ArgumentDeducer;928#ifndef WIN32929friend class detail::Child;930#endif932template <typename... Args>933Popen(std::initializer_list<const char*> cmd_args, Args&& ...args)934{935vargs_.insert(vargs_.end(), cmd_args.begin(), cmd_args.end());936init_args(std::forward<Args>(args)...);938// Setup the communication channels of the Popen class939stream_.setup_comm_channels();941execute_process();942}944template <typename... Args>945Popen(std::vector<std::string> vargs_, Args &&... args) : vargs_(vargs_)946{947init_args(std::forward<Args>(args)...);949// Setup the communication channels of the Popen class950stream_.setup_comm_channels();952execute_process();953}955int retcode() const noexcept { return retcode_; }957int wait() noexcept(false);959void set_out_buf_cap(size_t cap) { stream_.set_out_buf_cap(cap); }961void set_err_buf_cap(size_t cap) { stream_.set_err_buf_cap(cap); }963int send(const char* msg, size_t length)964{ return stream_.send(msg, length); }966int send(const std::string& msg)967{ return send(msg.c_str(), msg.size()); }969int send(const std::vector<char>& msg)970{ return stream_.send(msg); }972std::pair<OutBuffer, ErrBuffer> communicate(const char* msg, size_t length)973{974auto res = stream_.communicate(msg, length);975retcode_ = wait();976return res;977}979std::pair<OutBuffer, ErrBuffer> communicate(const std::string& msg)980{981return communicate(msg.c_str(), msg.size());982}984std::pair<OutBuffer, ErrBuffer> communicate(const std::vector<char>& msg)985{986auto res = stream_.communicate(msg);987retcode_ = wait();988return res;989}991std::pair<OutBuffer, ErrBuffer> communicate()992{993return communicate(nullptr, 0);994}996private:997template <typename F, typename... Args>998void init_args(F&& farg, Args&&... args);999void init_args();1000void populate_c_argv();
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.