Bitcoin Core 29.99.0
P2P Digital Currency
subprocess.h
Go to the documentation of this file.
1// Based on the https://github.com/arun11299/cpp-subprocess project.
2
36#ifndef BITCOIN_UTIL_SUBPROCESS_H
37#define BITCOIN_UTIL_SUBPROCESS_H
38
39#include <util/syserror.h>
40
41#include <algorithm>
42#include <cassert>
43#include <csignal>
44#include <cstdio>
45#include <cstdlib>
46#include <cstring>
47#include <exception>
48#include <future>
49#include <initializer_list>
50#include <iostream>
51#include <locale>
52#include <map>
53#include <memory>
54#include <sstream>
55#include <string>
56#include <vector>
57
58#if (defined _MSC_VER) || (defined __MINGW32__)
59 #define __USING_WINDOWS__
60#endif
61
62#ifdef __USING_WINDOWS__
63 #include <codecvt>
64#endif
65
66extern "C" {
67#ifdef __USING_WINDOWS__
68 #include <windows.h>
69 #include <io.h>
70 #include <cwchar>
71#else
72 #include <sys/wait.h>
73 #include <unistd.h>
74#endif
75 #include <csignal>
76 #include <fcntl.h>
77 #include <sys/types.h>
78}
79
80// The Microsoft C++ compiler issues deprecation warnings
81// for the standard POSIX function names.
82// Its preferred implementations have a leading underscore.
83// See: https://learn.microsoft.com/en-us/cpp/c-runtime-library/compatibility.
84#if (defined _MSC_VER)
85 #define subprocess_close _close
86 #define subprocess_fileno _fileno
87 #define subprocess_open _open
88 #define subprocess_write _write
89#else
90 #define subprocess_close close
91 #define subprocess_fileno fileno
92 #define subprocess_open open
93 #define subprocess_write write
94#endif
95
119namespace subprocess {
120
121// Max buffer size allocated on stack for read error
122// from pipe
123static const size_t SP_MAX_ERR_BUF_SIZ = 1024;
124
125// Default buffer capacity for OutBuffer and ErrBuffer.
126// If the data exceeds this capacity, the buffer size is grown
127// by 1.5 times its previous capacity
128static const size_t DEFAULT_BUF_CAP_BYTES = 8192;
129
130
131/*-----------------------------------------------
132 * EXCEPTION CLASSES
133 *-----------------------------------------------
134 */
135
143class CalledProcessError: public std::runtime_error
144{
145public:
147 CalledProcessError(const std::string& error_msg, int retcode):
148 std::runtime_error(error_msg), retcode(retcode)
149 {}
150};
151
152
163class OSError: public std::runtime_error
164{
165public:
166 OSError(const std::string& err_msg, int err_code):
167 std::runtime_error(err_msg + ": " + SysErrorString(err_code))
168 {}
169};
170
171//--------------------------------------------------------------------
172namespace util
173{
174#ifdef __USING_WINDOWS__
175 inline void quote_argument(const std::wstring &argument, std::wstring &command_line,
176 bool force)
177 {
178 //
179 // Unless we're told otherwise, don't quote unless we actually
180 // need to do so --- hopefully avoid problems if programs won't
181 // parse quotes properly
182 //
183
184 if (force == false && argument.empty() == false &&
185 argument.find_first_of(L" \t\n\v") == argument.npos) {
186 command_line.append(argument);
187 }
188 else {
189 command_line.push_back(L'"');
190
191 for (auto it = argument.begin();; ++it) {
192 unsigned number_backslashes = 0;
193
194 while (it != argument.end() && *it == L'\\') {
195 ++it;
196 ++number_backslashes;
197 }
198
199 if (it == argument.end()) {
200
201 //
202 // Escape all backslashes, but let the terminating
203 // double quotation mark we add below be interpreted
204 // as a metacharacter.
205 //
206
207 command_line.append(number_backslashes * 2, L'\\');
208 break;
209 }
210 else if (*it == L'"') {
211
212 //
213 // Escape all backslashes and the following
214 // double quotation mark.
215 //
216
217 command_line.append(number_backslashes * 2 + 1, L'\\');
218 command_line.push_back(*it);
219 }
220 else {
221
222 //
223 // Backslashes aren't special here.
224 //
225
226 command_line.append(number_backslashes, L'\\');
227 command_line.push_back(*it);
228 }
229 }
230
231 command_line.push_back(L'"');
232 }
233 }
234
235 inline std::string get_last_error(DWORD errorMessageID)
236 {
237 if (errorMessageID == 0)
238 return std::string();
239
240 LPSTR messageBuffer = nullptr;
241 size_t size = FormatMessageA(
242 FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |
243 FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_MAX_WIDTH_MASK,
244 NULL, errorMessageID, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
245 (LPSTR)&messageBuffer, 0, NULL);
246
247 std::string message(messageBuffer, size);
248
249 LocalFree(messageBuffer);
250
251 return message;
252 }
253
254 inline FILE *file_from_handle(HANDLE h, const char *mode)
255 {
256 int md;
257 if (!mode) {
258 throw OSError("invalid_mode", 0);
259 }
260
261 if (mode[0] == 'w') {
262 md = _O_WRONLY;
263 }
264 else if (mode[0] == 'r') {
265 md = _O_RDONLY;
266 }
267 else {
268 throw OSError("file_from_handle", 0);
269 }
270
271 int os_fhandle = _open_osfhandle((intptr_t)h, md);
272 if (os_fhandle == -1) {
273 CloseHandle(h);
274 throw OSError("_open_osfhandle", 0);
275 }
276
277 FILE *fp = _fdopen(os_fhandle, mode);
278 if (fp == 0) {
279 subprocess_close(os_fhandle);
280 throw OSError("_fdopen", 0);
281 }
282
283 return fp;
284 }
285
286 inline void configure_pipe(HANDLE* read_handle, HANDLE* write_handle, HANDLE* child_handle)
287 {
288 SECURITY_ATTRIBUTES saAttr;
289
290 // Set the bInheritHandle flag so pipe handles are inherited.
291 saAttr.nLength = sizeof(SECURITY_ATTRIBUTES);
292 saAttr.bInheritHandle = TRUE;
293 saAttr.lpSecurityDescriptor = NULL;
294
295 // Create a pipe for the child process's STDIN.
296 if (!CreatePipe(read_handle, write_handle, &saAttr,0))
297 throw OSError("CreatePipe", 0);
298
299 // Ensure the write handle to the pipe for STDIN is not inherited.
300 if (!SetHandleInformation(*child_handle, HANDLE_FLAG_INHERIT, 0))
301 throw OSError("SetHandleInformation", 0);
302 }
303#endif
304
314 static inline std::vector<std::string>
315 split(const std::string& str, const std::string& delims=" \t")
316 {
317 std::vector<std::string> res;
318 size_t init = 0;
319
320 while (true) {
321 auto pos = str.find_first_of(delims, init);
322 if (pos == std::string::npos) {
323 res.emplace_back(str.substr(init, str.length()));
324 break;
325 }
326 res.emplace_back(str.substr(init, pos - init));
327 pos++;
328 init = pos;
329 }
330
331 return res;
332 }
333
334
335#ifndef __USING_WINDOWS__
345 static inline
346 void set_clo_on_exec(int fd, bool set = true)
347 {
348 int flags = fcntl(fd, F_GETFD, 0);
349 if (flags == -1) {
350 throw OSError("fcntl F_GETFD failed", errno);
351 }
352 if (set) flags |= FD_CLOEXEC;
353 else flags &= ~FD_CLOEXEC;
354 if (fcntl(fd, F_SETFD, flags) == -1) {
355 throw OSError("fcntl F_SETFD failed", errno);
356 }
357 }
358
359
369 static inline
370 std::pair<int, int> pipe_cloexec() noexcept(false)
371 {
372 int pipe_fds[2];
373 int res = pipe(pipe_fds);
374 if (res) {
375 throw OSError("pipe failure", errno);
376 }
377
378 set_clo_on_exec(pipe_fds[0]);
379 set_clo_on_exec(pipe_fds[1]);
380
381 return std::make_pair(pipe_fds[0], pipe_fds[1]);
382 }
383#endif
384
385
397 static inline
398 int write_n(int fd, const char* buf, size_t length)
399 {
400 size_t nwritten = 0;
401 while (nwritten < length) {
402 int written = subprocess_write(fd, buf + nwritten, length - nwritten);
403 if (written == -1) return -1;
404 nwritten += written;
405 }
406 return nwritten;
407 }
408
409
424 static inline
425 int read_atmost_n(FILE* fp, char* buf, size_t read_upto)
426 {
427#ifdef __USING_WINDOWS__
428 return (int)fread(buf, 1, read_upto, fp);
429#else
430 int fd = subprocess_fileno(fp);
431 int rbytes = 0;
432 int eintr_cnter = 0;
433
434 while (1) {
435 int read_bytes = read(fd, buf + rbytes, read_upto - rbytes);
436 if (read_bytes == -1) {
437 if (errno == EINTR) {
438 if (eintr_cnter >= 50) return -1;
439 eintr_cnter++;
440 continue;
441 }
442 return -1;
443 }
444 if (read_bytes == 0) return rbytes;
445
446 rbytes += read_bytes;
447 }
448 return rbytes;
449#endif
450 }
451
452
466 static inline int read_all(FILE* fp, std::vector<char>& buf)
467 {
468 auto buffer = buf.data();
469 int total_bytes_read = 0;
470 int fill_sz = buf.size();
471
472 while (1) {
473 const int rd_bytes = read_atmost_n(fp, buffer, fill_sz);
474
475 if (rd_bytes == -1) { // Read finished
476 if (total_bytes_read == 0) return -1;
477 break;
478
479 } else if (rd_bytes == fill_sz) { // Buffer full
480 const auto orig_sz = buf.size();
481 const auto new_sz = orig_sz * 2;
482 buf.resize(new_sz);
483 fill_sz = new_sz - orig_sz;
484
485 //update the buffer pointer
486 buffer = buf.data();
487 total_bytes_read += rd_bytes;
488 buffer += total_bytes_read;
489
490 } else { // Partial data ? Continue reading
491 total_bytes_read += rd_bytes;
492 fill_sz -= rd_bytes;
493 break;
494 }
495 }
496 buf.erase(buf.begin()+total_bytes_read, buf.end()); // remove extra nulls
497 return total_bytes_read;
498 }
499
500#ifndef __USING_WINDOWS__
514 static inline
515 std::pair<int, int> wait_for_child_exit(int pid)
516 {
517 int status = 0;
518 int ret = -1;
519 while (1) {
520 ret = waitpid(pid, &status, 0);
521 if (ret == -1) break;
522 if (ret == 0) continue;
523 return std::make_pair(ret, status);
524 }
525
526 return std::make_pair(ret, status);
527 }
528#endif
529
530} // end namespace util
531
532
533
534/* -------------------------------
535 * Popen Arguments
536 * -------------------------------
537 */
538
543{
544 string_arg(const char* arg): arg_value(arg) {}
545 string_arg(std::string&& arg): arg_value(std::move(arg)) {}
546 string_arg(const std::string& arg): arg_value(arg) {}
547 std::string arg_value;
548};
549
559{
560 template <typename T>
561 executable(T&& arg): string_arg(std::forward<T>(arg)) {}
562};
563
567enum IOTYPE {
571};
572
573//TODO: A common base/interface for below stream structures ??
574
586struct input
587{
588 // For an already existing file descriptor.
589 explicit input(int fd): rd_ch_(fd) {}
590
591 // FILE pointer.
592 explicit input (FILE* fp):input(subprocess_fileno(fp)) { assert(fp); }
593
594 explicit input(const char* filename) {
595 int fd = subprocess_open(filename, O_RDONLY);
596 if (fd == -1) throw OSError("File not found: ", errno);
597 rd_ch_ = fd;
598 }
599 explicit input(IOTYPE typ) {
600 assert (typ == PIPE && "STDOUT/STDERR not allowed");
601#ifndef __USING_WINDOWS__
602 std::tie(rd_ch_, wr_ch_) = util::pipe_cloexec();
603#endif
604 }
605
606 int rd_ch_ = -1;
607 int wr_ch_ = -1;
608};
609
610
621struct output
622{
623 explicit output(int fd): wr_ch_(fd) {}
624
625 explicit output (FILE* fp):output(subprocess_fileno(fp)) { assert(fp); }
626
627 explicit output(const char* filename) {
628 int fd = subprocess_open(filename, O_APPEND | O_CREAT | O_RDWR, 0640);
629 if (fd == -1) throw OSError("File not found: ", errno);
630 wr_ch_ = fd;
631 }
632 explicit output(IOTYPE typ) {
633 assert (typ == PIPE && "STDOUT/STDERR not allowed");
634#ifndef __USING_WINDOWS__
635 std::tie(rd_ch_, wr_ch_) = util::pipe_cloexec();
636#endif
637 }
638
639 int rd_ch_ = -1;
640 int wr_ch_ = -1;
641};
642
643
652struct error
653{
654 explicit error(int fd): wr_ch_(fd) {}
655
656 explicit error(FILE* fp):error(subprocess_fileno(fp)) { assert(fp); }
657
658 explicit error(const char* filename) {
659 int fd = subprocess_open(filename, O_APPEND | O_CREAT | O_RDWR, 0640);
660 if (fd == -1) throw OSError("File not found: ", errno);
661 wr_ch_ = fd;
662 }
663 explicit error(IOTYPE typ) {
664 assert ((typ == PIPE || typ == STDOUT) && "STDERR not allowed");
665 if (typ == PIPE) {
666#ifndef __USING_WINDOWS__
667 std::tie(rd_ch_, wr_ch_) = util::pipe_cloexec();
668#endif
669 } else {
670 // Need to defer it till we have checked all arguments
671 deferred_ = true;
672 }
673 }
674
675 bool deferred_ = false;
676 int rd_ch_ = -1;
677 int wr_ch_ = -1;
678};
679
680// ~~~~ End Popen Args ~~~~
681
682
695{
696public:
697 Buffer() = default;
698 explicit Buffer(size_t cap) { buf.resize(cap); }
699 void add_cap(size_t cap) { buf.resize(cap); }
700
701public:
702 std::vector<char> buf;
703 size_t length = 0;
704};
705
706// Buffer for storing output written to output fd
708// Buffer for storing output written to error fd
710
711
712// Fwd Decl.
713class Popen;
714
715/*---------------------------------------------------
716 * DETAIL NAMESPACE
717 *---------------------------------------------------
718 */
719
720namespace detail {
729{
731
732 void set_option(executable&& exe);
733 void set_option(input&& inp);
734 void set_option(output&& out);
735 void set_option(error&& err);
736
737private:
738 Popen* popen_ = nullptr;
739};
740
746class Child
747{
748public:
749 Child(Popen* p, int err_wr_pipe):
750 parent_(p),
751 err_wr_pipe_(err_wr_pipe)
752 {}
753
754 void execute_child();
755
756private:
757 // Lets call it parent even though
758 // technically a bit incorrect
759 Popen* parent_ = nullptr;
760 int err_wr_pipe_ = -1;
761};
762
763// Fwd Decl.
764class Streams;
765
773{
774public:
775 Communication(Streams* stream): stream_(stream)
776 {}
777 Communication(const Communication&) = delete;
781public:
782 int send(const char* msg, size_t length);
783 int send(const std::vector<char>& msg);
784
785 std::pair<OutBuffer, ErrBuffer> communicate(const char* msg, size_t length);
786 std::pair<OutBuffer, ErrBuffer> communicate(const std::vector<char>& msg)
787 { return communicate(msg.data(), msg.size()); }
788
789 void set_out_buf_cap(size_t cap) { out_buf_cap_ = cap; }
790 void set_err_buf_cap(size_t cap) { err_buf_cap_ = cap; }
791
792private:
793 std::pair<OutBuffer, ErrBuffer> communicate_threaded(
794 const char* msg, size_t length);
795
796private:
800};
801
802
803
814{
815public:
816 Streams():comm_(this) {}
817 Streams(const Streams&) = delete;
818 Streams& operator=(const Streams&) = delete;
819 Streams(Streams&&) = default;
820 Streams& operator=(Streams&&) = default;
821
822public:
823 void setup_comm_channels();
824
826 {
827 if (write_to_child_ != -1 && read_from_parent_ != -1) {
829 }
830 if (write_to_parent_ != -1 && read_from_child_ != -1) {
832 }
833 if (err_write_ != -1 && err_read_ != -1) {
835 }
836 }
837
839 {
843 }
844
846 {
850 }
851
852 FILE* input() { return input_.get(); }
853 FILE* output() { return output_.get(); }
854 FILE* error() { return error_.get(); }
855
856 void input(FILE* fp) { input_.reset(fp, fclose); }
857 void output(FILE* fp) { output_.reset(fp, fclose); }
858 void error(FILE* fp) { error_.reset(fp, fclose); }
859
860 void set_out_buf_cap(size_t cap) { comm_.set_out_buf_cap(cap); }
861 void set_err_buf_cap(size_t cap) { comm_.set_err_buf_cap(cap); }
862
863public: /* Communication forwarding API's */
864 int send(const char* msg, size_t length)
865 { return comm_.send(msg, length); }
866
867 int send(const std::vector<char>& msg)
868 { return comm_.send(msg); }
869
870 std::pair<OutBuffer, ErrBuffer> communicate(const char* msg, size_t length)
871 { return comm_.communicate(msg, length); }
872
873 std::pair<OutBuffer, ErrBuffer> communicate(const std::vector<char>& msg)
874 { return comm_.communicate(msg); }
875
876
877public:// Yes they are public
878
879 std::shared_ptr<FILE> input_ = nullptr;
880 std::shared_ptr<FILE> output_ = nullptr;
881 std::shared_ptr<FILE> error_ = nullptr;
882
883#ifdef __USING_WINDOWS__
884 HANDLE g_hChildStd_IN_Rd = nullptr;
885 HANDLE g_hChildStd_IN_Wr = nullptr;
886 HANDLE g_hChildStd_OUT_Rd = nullptr;
887 HANDLE g_hChildStd_OUT_Wr = nullptr;
888 HANDLE g_hChildStd_ERR_Rd = nullptr;
889 HANDLE g_hChildStd_ERR_Wr = nullptr;
890#endif
891
892 // Pipes for communicating with child
893
894 // Emulates stdin
895 int write_to_child_ = -1; // Parent owned descriptor
896 int read_from_parent_ = -1; // Child owned descriptor
897
898 // Emulates stdout
899 int write_to_parent_ = -1; // Child owned descriptor
900 int read_from_child_ = -1; // Parent owned descriptor
901
902 // Emulates stderr
903 int err_write_ = -1; // Write error to parent (Child owned)
904 int err_read_ = -1; // Read error from child (Parent owned)
905
906private:
908};
909
910} // end namespace detail
911
912
913
931class Popen
932{
933public:
935 friend class detail::Child;
936
937 template <typename... Args>
938 Popen(const std::string& cmd_args, Args&& ...args):
939 args_(cmd_args)
940 {
941 vargs_ = util::split(cmd_args);
942 init_args(std::forward<Args>(args)...);
943
944 // Setup the communication channels of the Popen class
946
948 }
949
950 template <typename... Args>
951 Popen(std::initializer_list<const char*> cmd_args, Args&& ...args)
952 {
953 vargs_.insert(vargs_.end(), cmd_args.begin(), cmd_args.end());
954 init_args(std::forward<Args>(args)...);
955
956 // Setup the communication channels of the Popen class
958
960 }
961
962 template <typename... Args>
963 Popen(std::vector<std::string> vargs_, Args &&... args) : vargs_(vargs_)
964 {
965 init_args(std::forward<Args>(args)...);
966
967 // Setup the communication channels of the Popen class
969
971 }
972
973 int retcode() const noexcept { return retcode_; }
974
975 int wait() noexcept(false);
976
977 void set_out_buf_cap(size_t cap) { stream_.set_out_buf_cap(cap); }
978
979 void set_err_buf_cap(size_t cap) { stream_.set_err_buf_cap(cap); }
980
981 int send(const char* msg, size_t length)
982 { return stream_.send(msg, length); }
983
984 int send(const std::string& msg)
985 { return send(msg.c_str(), msg.size()); }
986
987 int send(const std::vector<char>& msg)
988 { return stream_.send(msg); }
989
990 std::pair<OutBuffer, ErrBuffer> communicate(const char* msg, size_t length)
991 {
992 auto res = stream_.communicate(msg, length);
993 retcode_ = wait();
994 return res;
995 }
996
997 std::pair<OutBuffer, ErrBuffer> communicate(const std::string& msg)
998 {
999 return communicate(msg.c_str(), msg.size());
1000 }
1001
1002 std::pair<OutBuffer, ErrBuffer> communicate(const std::vector<char>& msg)
1003 {
1004 auto res = stream_.communicate(msg);
1005 retcode_ = wait();
1006 return res;
1007 }
1008
1009 std::pair<OutBuffer, ErrBuffer> communicate()
1010 {
1011 return communicate(nullptr, 0);
1012 }
1013
1014private:
1015 template <typename F, typename... Args>
1016 void init_args(F&& farg, Args&&... args);
1017 void init_args();
1018 void populate_c_argv();
1019 void execute_process() noexcept(false);
1020
1021private:
1022 detail::Streams stream_;
1023
1024#ifdef __USING_WINDOWS__
1025 HANDLE process_handle_;
1026 std::future<void> cleanup_future_;
1027#endif
1028
1029 std::string exe_name_;
1030
1031 // Command in string format
1032 std::string args_;
1033 // Command provided as sequence
1034 std::vector<std::string> vargs_;
1035 std::vector<char*> cargv_;
1036
1037 // Pid of the child process
1038 int child_pid_ = -1;
1039
1040 int retcode_ = -1;
1041};
1042
1043inline void Popen::init_args() {
1045}
1046
1047template <typename F, typename... Args>
1048inline void Popen::init_args(F&& farg, Args&&... args)
1049{
1050 detail::ArgumentDeducer argd(this);
1051 argd.set_option(std::forward<F>(farg));
1052 init_args(std::forward<Args>(args)...);
1053}
1054
1056{
1057 cargv_.clear();
1058 cargv_.reserve(vargs_.size() + 1);
1059 for (auto& arg : vargs_) cargv_.push_back(&arg[0]);
1060 cargv_.push_back(nullptr);
1061}
1062
1063inline int Popen::wait() noexcept(false)
1064{
1065#ifdef __USING_WINDOWS__
1066 int ret = WaitForSingleObject(process_handle_, INFINITE);
1067
1068 // WaitForSingleObject with INFINITE should only return when process has signaled
1069 if (ret != WAIT_OBJECT_0) {
1070 throw OSError("Unexpected return code from WaitForSingleObject", 0);
1071 }
1072
1073 DWORD dretcode_;
1074
1075 if (FALSE == GetExitCodeProcess(process_handle_, &dretcode_))
1076 throw OSError("Failed during call to GetExitCodeProcess", 0);
1077
1078 CloseHandle(process_handle_);
1079
1080 return (int)dretcode_;
1081#else
1082 int ret, status;
1083 std::tie(ret, status) = util::wait_for_child_exit(child_pid_);
1084 if (ret == -1) {
1085 if (errno != ECHILD) throw OSError("waitpid failed", errno);
1086 return 0;
1087 }
1088 if (WIFEXITED(status)) return WEXITSTATUS(status);
1089 if (WIFSIGNALED(status)) return WTERMSIG(status);
1090 else return 255;
1091
1092 return 0;
1093#endif
1094}
1095
1096inline void Popen::execute_process() noexcept(false)
1097{
1098#ifdef __USING_WINDOWS__
1099 if (exe_name_.length()) {
1100 this->vargs_.insert(this->vargs_.begin(), this->exe_name_);
1101 this->populate_c_argv();
1102 }
1103 this->exe_name_ = vargs_[0];
1104
1105 std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> converter;
1106 std::wstring argument;
1107 std::wstring command_line;
1108
1109 for (auto arg : this->vargs_) {
1110 argument = converter.from_bytes(arg);
1111 util::quote_argument(argument, command_line, false);
1112 command_line += L" ";
1113 }
1114
1115 // CreateProcessW can modify szCmdLine so we allocate needed memory
1116 wchar_t *szCmdline = new wchar_t[command_line.size() + 1];
1117 wcscpy_s(szCmdline, command_line.size() + 1, command_line.c_str());
1118 PROCESS_INFORMATION piProcInfo;
1119 STARTUPINFOW siStartInfo;
1120 BOOL bSuccess = FALSE;
1121 DWORD creation_flags = CREATE_UNICODE_ENVIRONMENT | CREATE_NO_WINDOW;
1122
1123 // Set up members of the PROCESS_INFORMATION structure.
1124 ZeroMemory(&piProcInfo, sizeof(PROCESS_INFORMATION));
1125
1126 // Set up members of the STARTUPINFOW structure.
1127 // This structure specifies the STDIN and STDOUT handles for redirection.
1128
1129 ZeroMemory(&siStartInfo, sizeof(STARTUPINFOW));
1130 siStartInfo.cb = sizeof(STARTUPINFOW);
1131
1132 siStartInfo.hStdError = this->stream_.g_hChildStd_ERR_Wr;
1133 siStartInfo.hStdOutput = this->stream_.g_hChildStd_OUT_Wr;
1134 siStartInfo.hStdInput = this->stream_.g_hChildStd_IN_Rd;
1135
1136 siStartInfo.dwFlags |= STARTF_USESTDHANDLES;
1137
1138 // Create the child process.
1139 bSuccess = CreateProcessW(NULL,
1140 szCmdline, // command line
1141 NULL, // process security attributes
1142 NULL, // primary thread security attributes
1143 TRUE, // handles are inherited
1144 creation_flags, // creation flags
1145 NULL, // use parent's environment
1146 NULL, // use parent's current directory
1147 &siStartInfo, // STARTUPINFOW pointer
1148 &piProcInfo); // receives PROCESS_INFORMATION
1149
1150 // If an error occurs, exit the application.
1151 if (!bSuccess) {
1152 DWORD errorMessageID = ::GetLastError();
1153 throw CalledProcessError("CreateProcess failed: " + util::get_last_error(errorMessageID), errorMessageID);
1154 }
1155
1156 CloseHandle(piProcInfo.hThread);
1157
1158 /*
1159 TODO: use common apis to close linux handles
1160 */
1161
1162 this->process_handle_ = piProcInfo.hProcess;
1163
1164 this->cleanup_future_ = std::async(std::launch::async, [this] {
1165 WaitForSingleObject(this->process_handle_, INFINITE);
1166
1167 CloseHandle(this->stream_.g_hChildStd_ERR_Wr);
1168 CloseHandle(this->stream_.g_hChildStd_OUT_Wr);
1169 CloseHandle(this->stream_.g_hChildStd_IN_Rd);
1170 });
1171
1172/*
1173 NOTE: In the linux version, there is a check to make sure that the process
1174 has been started. Here, we do nothing because CreateProcess will throw
1175 if we fail to create the process.
1176*/
1177
1178
1179#else
1180
1181 int err_rd_pipe, err_wr_pipe;
1182 std::tie(err_rd_pipe, err_wr_pipe) = util::pipe_cloexec();
1183
1184 if (exe_name_.length()) {
1185 vargs_.insert(vargs_.begin(), exe_name_);
1187 }
1188 exe_name_ = vargs_[0];
1189
1190 child_pid_ = fork();
1191
1192 if (child_pid_ < 0) {
1193 subprocess_close(err_rd_pipe);
1194 subprocess_close(err_wr_pipe);
1195 throw OSError("fork failed", errno);
1196 }
1197
1198 if (child_pid_ == 0)
1199 {
1200 // Close descriptors belonging to parent
1202
1203 //Close the read end of the error pipe
1204 subprocess_close(err_rd_pipe);
1205
1206 detail::Child chld(this, err_wr_pipe);
1207 chld.execute_child();
1208 }
1209 else
1210 {
1211 subprocess_close(err_wr_pipe);// close child side of pipe, else get stuck in read below
1212
1214
1215 try {
1216 char err_buf[SP_MAX_ERR_BUF_SIZ] = {0,};
1217
1218 FILE* err_fp = fdopen(err_rd_pipe, "r");
1219 if (!err_fp) {
1220 subprocess_close(err_rd_pipe);
1221 throw OSError("fdopen failed", errno);
1222 }
1223 int read_bytes = util::read_atmost_n(err_fp, err_buf, SP_MAX_ERR_BUF_SIZ);
1224 fclose(err_fp);
1225
1226 if (read_bytes || strlen(err_buf)) {
1227 // Call waitpid to reap the child process
1228 // waitpid suspends the calling process until the
1229 // child terminates.
1230 int retcode = wait();
1231
1232 // Throw whatever information we have about child failure
1233 throw CalledProcessError(err_buf, retcode);
1234 }
1235 } catch (std::exception& exp) {
1237 throw;
1238 }
1239
1240 }
1241#endif
1242}
1243
1244namespace detail {
1245
1247 popen_->exe_name_ = std::move(exe.arg_value);
1248 }
1249
1251 if (inp.rd_ch_ != -1) popen_->stream_.read_from_parent_ = inp.rd_ch_;
1252 if (inp.wr_ch_ != -1) popen_->stream_.write_to_child_ = inp.wr_ch_;
1253 }
1254
1256 if (out.wr_ch_ != -1) popen_->stream_.write_to_parent_ = out.wr_ch_;
1257 if (out.rd_ch_ != -1) popen_->stream_.read_from_child_ = out.rd_ch_;
1258 }
1259
1261 if (err.deferred_) {
1264 } else {
1265 throw std::runtime_error("Set output before redirecting error to output");
1266 }
1267 }
1268 if (err.wr_ch_ != -1) popen_->stream_.err_write_ = err.wr_ch_;
1269 if (err.rd_ch_ != -1) popen_->stream_.err_read_ = err.rd_ch_;
1270 }
1271
1272
1273 inline void Child::execute_child() {
1274#ifndef __USING_WINDOWS__
1275 int sys_ret = -1;
1276 auto& stream = parent_->stream_;
1277
1278 try {
1279 if (stream.write_to_parent_ == 0)
1280 stream.write_to_parent_ = dup(stream.write_to_parent_);
1281
1282 if (stream.err_write_ == 0 || stream.err_write_ == 1)
1283 stream.err_write_ = dup(stream.err_write_);
1284
1285 // Make the child owned descriptors as the
1286 // stdin, stdout and stderr for the child process
1287 auto _dup2_ = [](int fd, int to_fd) {
1288 if (fd == to_fd) {
1289 // dup2 syscall does not reset the
1290 // CLOEXEC flag if the descriptors
1291 // provided to it are same.
1292 // But, we need to reset the CLOEXEC
1293 // flag as the provided descriptors
1294 // are now going to be the standard
1295 // input, output and error
1296 util::set_clo_on_exec(fd, false);
1297 } else if(fd != -1) {
1298 int res = dup2(fd, to_fd);
1299 if (res == -1) throw OSError("dup2 failed", errno);
1300 }
1301 };
1302
1303 // Create the standard streams
1304 _dup2_(stream.read_from_parent_, 0); // Input stream
1305 _dup2_(stream.write_to_parent_, 1); // Output stream
1306 _dup2_(stream.err_write_, 2); // Error stream
1307
1308 // Close the duped descriptors
1309 if (stream.read_from_parent_ != -1 && stream.read_from_parent_ > 2)
1310 subprocess_close(stream.read_from_parent_);
1311
1312 if (stream.write_to_parent_ != -1 && stream.write_to_parent_ > 2)
1313 subprocess_close(stream.write_to_parent_);
1314
1315 if (stream.err_write_ != -1 && stream.err_write_ > 2)
1316 subprocess_close(stream.err_write_);
1317
1318 // Replace the current image with the executable
1319 sys_ret = execvp(parent_->exe_name_.c_str(), parent_->cargv_.data());
1320
1321 if (sys_ret == -1) throw OSError("execve failed", errno);
1322
1323 } catch (const OSError& exp) {
1324 // Just write the exception message
1325 // TODO: Give back stack trace ?
1326 std::string err_msg(exp.what());
1327 //ATTN: Can we do something on error here ?
1328 util::write_n(err_wr_pipe_, err_msg.c_str(), err_msg.length());
1329 }
1330
1331 // Calling application would not get this
1332 // exit failure
1333 _exit (EXIT_FAILURE);
1334#endif
1335 }
1336
1337
1339 {
1340#ifdef __USING_WINDOWS__
1341 util::configure_pipe(&this->g_hChildStd_IN_Rd, &this->g_hChildStd_IN_Wr, &this->g_hChildStd_IN_Wr);
1342 this->input(util::file_from_handle(this->g_hChildStd_IN_Wr, "w"));
1343 this->write_to_child_ = subprocess_fileno(this->input());
1344
1345 util::configure_pipe(&this->g_hChildStd_OUT_Rd, &this->g_hChildStd_OUT_Wr, &this->g_hChildStd_OUT_Rd);
1346 this->output(util::file_from_handle(this->g_hChildStd_OUT_Rd, "r"));
1347 this->read_from_child_ = subprocess_fileno(this->output());
1348
1349 util::configure_pipe(&this->g_hChildStd_ERR_Rd, &this->g_hChildStd_ERR_Wr, &this->g_hChildStd_ERR_Rd);
1350 this->error(util::file_from_handle(this->g_hChildStd_ERR_Rd, "r"));
1351 this->err_read_ = subprocess_fileno(this->error());
1352#else
1353
1354 if (write_to_child_ != -1) input(fdopen(write_to_child_, "wb"));
1355 if (read_from_child_ != -1) output(fdopen(read_from_child_, "rb"));
1356 if (err_read_ != -1) error(fdopen(err_read_, "rb"));
1357
1358 auto handles = {input(), output(), error()};
1359
1360 for (auto& h : handles) {
1361 if (h == nullptr) continue;
1362 setvbuf(h, nullptr, _IONBF, BUFSIZ);
1363 }
1364 #endif
1365 }
1366
1367 inline int Communication::send(const char* msg, size_t length)
1368 {
1369 if (stream_->input() == nullptr) return -1;
1370 return std::fwrite(msg, sizeof(char), length, stream_->input());
1371 }
1372
1373 inline int Communication::send(const std::vector<char>& msg)
1374 {
1375 return send(msg.data(), msg.size());
1376 }
1377
1378 inline std::pair<OutBuffer, ErrBuffer>
1379 Communication::communicate(const char* msg, size_t length)
1380 {
1381 // Optimization from subprocess.py
1382 // If we are using one pipe, or no pipe
1383 // at all, using select() or threads is unnecessary.
1384 auto hndls = {stream_->input(), stream_->output(), stream_->error()};
1385 int count = std::count(std::begin(hndls), std::end(hndls), nullptr);
1386 const int len_conv = length;
1387
1388 if (count >= 2) {
1389 OutBuffer obuf;
1390 ErrBuffer ebuf;
1391 if (stream_->input()) {
1392 if (msg) {
1393 int wbytes = std::fwrite(msg, sizeof(char), length, stream_->input());
1394 if (wbytes < len_conv) {
1395 if (errno != EPIPE && errno != EINVAL) {
1396 throw OSError("fwrite error", errno);
1397 }
1398 }
1399 }
1400 // Close the input stream
1401 stream_->input_.reset();
1402 } else if (stream_->output()) {
1403 // Read till EOF
1404 // ATTN: This could be blocking, if the process
1405 // at the other end screws up, we get screwed as well
1406 obuf.add_cap(out_buf_cap_);
1407
1408 int rbytes = util::read_all(
1409 stream_->output(),
1410 obuf.buf);
1411
1412 if (rbytes == -1) {
1413 throw OSError("read to obuf failed", errno);
1414 }
1415
1416 obuf.length = rbytes;
1417 // Close the output stream
1418 stream_->output_.reset();
1419
1420 } else if (stream_->error()) {
1421 // Same screwness applies here as well
1422 ebuf.add_cap(err_buf_cap_);
1423
1424 int rbytes = util::read_atmost_n(
1425 stream_->error(),
1426 ebuf.buf.data(),
1427 ebuf.buf.size());
1428
1429 if (rbytes == -1) {
1430 throw OSError("read to ebuf failed", errno);
1431 }
1432
1433 ebuf.length = rbytes;
1434 // Close the error stream
1435 stream_->error_.reset();
1436 }
1437 return std::make_pair(std::move(obuf), std::move(ebuf));
1438 }
1439
1440 return communicate_threaded(msg, length);
1441 }
1442
1443
1444 inline std::pair<OutBuffer, ErrBuffer>
1445 Communication::communicate_threaded(const char* msg, size_t length)
1446 {
1447 OutBuffer obuf;
1448 ErrBuffer ebuf;
1449 std::future<int> out_fut, err_fut;
1450 const int length_conv = length;
1451
1452 if (stream_->output()) {
1453 obuf.add_cap(out_buf_cap_);
1454
1455 out_fut = std::async(std::launch::async,
1456 [&obuf, this] {
1457 return util::read_all(this->stream_->output(), obuf.buf);
1458 });
1459 }
1460 if (stream_->error()) {
1461 ebuf.add_cap(err_buf_cap_);
1462
1463 err_fut = std::async(std::launch::async,
1464 [&ebuf, this] {
1465 return util::read_all(this->stream_->error(), ebuf.buf);
1466 });
1467 }
1468 if (stream_->input()) {
1469 if (msg) {
1470 int wbytes = std::fwrite(msg, sizeof(char), length, stream_->input());
1471 if (wbytes < length_conv) {
1472 if (errno != EPIPE && errno != EINVAL) {
1473 throw OSError("fwrite error", errno);
1474 }
1475 }
1476 }
1477 stream_->input_.reset();
1478 }
1479
1480 if (out_fut.valid()) {
1481 int res = out_fut.get();
1482 if (res != -1) obuf.length = res;
1483 else obuf.length = 0;
1484 }
1485 if (err_fut.valid()) {
1486 int res = err_fut.get();
1487 if (res != -1) ebuf.length = res;
1488 else ebuf.length = 0;
1489 }
1490
1491 return std::make_pair(std::move(obuf), std::move(ebuf));
1492 }
1493
1494} // end namespace detail
1495
1496}
1497
1498#endif // BITCOIN_UTIL_SUBPROCESS_H
int ret
int flags
Definition: bitcoin-tx.cpp:536
ArgsManager & args
Definition: bitcoind.cpp:277
Buffer(size_t cap)
Definition: subprocess.h:698
void add_cap(size_t cap)
Definition: subprocess.h:699
std::vector< char > buf
Definition: subprocess.h:702
CalledProcessError(const std::string &error_msg, int retcode)
Definition: subprocess.h:147
OSError(const std::string &err_msg, int err_code)
Definition: subprocess.h:166
std::pair< OutBuffer, ErrBuffer > communicate(const char *msg, size_t length)
Definition: subprocess.h:990
void populate_c_argv()
Definition: subprocess.h:1055
detail::Streams stream_
Definition: subprocess.h:1022
std::pair< OutBuffer, ErrBuffer > communicate(const std::string &msg)
Definition: subprocess.h:997
void set_out_buf_cap(size_t cap)
Definition: subprocess.h:977
Popen(std::initializer_list< const char * > cmd_args, Args &&...args)
Definition: subprocess.h:951
std::vector< char * > cargv_
Definition: subprocess.h:1035
Popen(std::vector< std::string > vargs_, Args &&... args)
Definition: subprocess.h:963
void execute_process() noexcept(false)
Definition: subprocess.h:1096
std::vector< std::string > vargs_
Definition: subprocess.h:1034
std::string exe_name_
Definition: subprocess.h:1029
int send(const std::vector< char > &msg)
Definition: subprocess.h:987
int send(const std::string &msg)
Definition: subprocess.h:984
std::pair< OutBuffer, ErrBuffer > communicate()
Definition: subprocess.h:1009
std::pair< OutBuffer, ErrBuffer > communicate(const std::vector< char > &msg)
Definition: subprocess.h:1002
int retcode() const noexcept
Definition: subprocess.h:973
Popen(const std::string &cmd_args, Args &&...args)
Definition: subprocess.h:938
int wait() noexcept(false)
Definition: subprocess.h:1063
void set_err_buf_cap(size_t cap)
Definition: subprocess.h:979
int send(const char *msg, size_t length)
Definition: subprocess.h:981
std::string args_
Definition: subprocess.h:1032
Child(Popen *p, int err_wr_pipe)
Definition: subprocess.h:749
void set_err_buf_cap(size_t cap)
Definition: subprocess.h:790
Communication(Communication &&)=default
void set_out_buf_cap(size_t cap)
Definition: subprocess.h:789
int send(const char *msg, size_t length)
Definition: subprocess.h:1367
std::pair< OutBuffer, ErrBuffer > communicate(const char *msg, size_t length)
Definition: subprocess.h:1379
std::pair< OutBuffer, ErrBuffer > communicate_threaded(const char *msg, size_t length)
Definition: subprocess.h:1445
Communication & operator=(const Communication &)=delete
Communication(const Communication &)=delete
Communication & operator=(Communication &&)=default
std::pair< OutBuffer, ErrBuffer > communicate(const std::vector< char > &msg)
Definition: subprocess.h:786
std::pair< OutBuffer, ErrBuffer > communicate(const std::vector< char > &msg)
Definition: subprocess.h:873
int send(const std::vector< char > &msg)
Definition: subprocess.h:867
void set_out_buf_cap(size_t cap)
Definition: subprocess.h:860
Streams(Streams &&)=default
std::pair< OutBuffer, ErrBuffer > communicate(const char *msg, size_t length)
Definition: subprocess.h:870
void set_err_buf_cap(size_t cap)
Definition: subprocess.h:861
std::shared_ptr< FILE > output_
Definition: subprocess.h:880
std::shared_ptr< FILE > error_
Definition: subprocess.h:881
Streams & operator=(const Streams &)=delete
int send(const char *msg, size_t length)
Definition: subprocess.h:864
Streams(const Streams &)=delete
Streams & operator=(Streams &&)=default
std::shared_ptr< FILE > input_
Definition: subprocess.h:879
#define T(expected, seed, data)
static int read_all(FILE *fp, std::vector< char > &buf)
Definition: subprocess.h:466
static int read_atmost_n(FILE *fp, char *buf, size_t read_upto)
Definition: subprocess.h:425
static void set_clo_on_exec(int fd, bool set=true)
Definition: subprocess.h:346
static std::vector< std::string > split(const std::string &str, const std::string &delims=" \t")
Definition: subprocess.h:315
static std::pair< int, int > wait_for_child_exit(int pid)
Definition: subprocess.h:515
static std::pair< int, int > pipe_cloexec() noexcept(false)
Definition: subprocess.h:370
static int write_n(int fd, const char *buf, size_t length)
Definition: subprocess.h:398
static const size_t SP_MAX_ERR_BUF_SIZ
Definition: subprocess.h:123
static const size_t DEFAULT_BUF_CAP_BYTES
Definition: subprocess.h:128
void set_option(executable &&exe)
Definition: subprocess.h:1246
error(FILE *fp)
Definition: subprocess.h:656
error(IOTYPE typ)
Definition: subprocess.h:663
error(const char *filename)
Definition: subprocess.h:658
input(const char *filename)
Definition: subprocess.h:594
input(IOTYPE typ)
Definition: subprocess.h:599
input(FILE *fp)
Definition: subprocess.h:592
output(IOTYPE typ)
Definition: subprocess.h:632
output(const char *filename)
Definition: subprocess.h:627
output(FILE *fp)
Definition: subprocess.h:625
std::string arg_value
Definition: subprocess.h:547
string_arg(const char *arg)
Definition: subprocess.h:544
string_arg(std::string &&arg)
Definition: subprocess.h:545
string_arg(const std::string &arg)
Definition: subprocess.h:546
#define subprocess_close
Definition: subprocess.h:90
#define subprocess_write
Definition: subprocess.h:93
#define subprocess_fileno
Definition: subprocess.h:91
#define subprocess_open
Definition: subprocess.h:92
std::string SysErrorString(int err)
Return system error string from errno value.
Definition: syserror.cpp:19
static int count
assert(!tx.IsCoinBase())