From 2224a2802cd76d80b865b7cd8a5449279e841954 Mon Sep 17 00:00:00 2001 From: arunmu Date: Tue, 15 Mar 2016 18:54:12 +0530 Subject: [PATCH] FD_CLOEXEC fix --- main | Bin 73372 -> 106170 bytes s.py | 6 +- subprocess.hpp | 388 ++++++++++++++++++++++++++----------------------- 3 files changed, 209 insertions(+), 185 deletions(-) mode change 100644 => 100755 s.py diff --git a/main b/main index b5147d798922936c51162d67d7109f1a2d1270df..bc0add85f095a657af3228754ad6faf60ea30f63 100755 GIT binary patch literal 106170 zcmeFaeSB2K^*??$4-gR{B5Fj`RRKW(10o`zE)T&)gGL@KS|EWWNGuOA4~P^j5}>Rh znp(7I`PkG_ORd_}Qi>EY2qn>4j7l{{s;O1GF;r8fHd-{l_xsGuy|bIWslV^*`~B~; zyvTd!oHJ+6oH=u5?%cb(-^t3Jk`xFy=9T1J?XXmRPDn`VujA}`U5c7E#yQCeIp;b3 zoo=9{;(tguMD@;KyH;&5P0J+%Q}BOGk|K;r3dtLT{S_H4sF$&j$o9NfNWWG1+)Jux z&~bu7U_IIz{i76tdGf|!9*w~(v%5l5kLIyn+95?xJCrAH47O>*44VE?9skeN{hOH- zLW$)N!I><7J=D!RIq#Ph@O}EdN+A8-ki0Q?^khXhXzJaBdbIQFzS6beblskxUoy1) z26cCxOBWX{7(MFJ#RbC_7cDJcF>J+{(ZfcM8eY0=_(WdrO~ilJfEjQ&;9=LO+4F!JfzuFZ<9hgWrPqAOAYrNB%|#2IGZMKIr3zjo>A+=N2FP zzrdtSBtOrGzS>96?|l6EQy=;dedtSl^xxz|-{M2Rz=xjVLtpMgALuhK%!`Tqw%5mR zMHrVL{>Q&A^6|q_pLXkgO{-h86K_C0yg#!}#?MFWTzr)AR zfAwj1qffhweDpu!qvxAG@_&av&v*Jc4X@?NP|nr^x*14%@O4G!ddJuAU=Qhehx4S& z{L9xJXqWV2O*eW@(ewsQ4=ZtJ2J~FuoZ^hTCM1*vnm$R}nb%*@HQ5=h{Z<=C|EH!G z>wTV)e_hAPnmGDL5D@!ye+TOdcR~;88#O(o>5H_U#(svP7;8X374jkNpLFzxuV3Lm z<6+I&A^i1TSL<n#e za`W-74C1%mFr#$Rh^*!6-DQPK3*`OGsWZw(Tvk%Pw5(`JVQyhb$+8ki6fDkxU~c}3 z`MJgAC55@mi%QDM=Pw3lM%l>B++65ic4zM5!lk#BEmD3V<0gx7(&qfdiRhXO?rkep-@51B~x?qXOw1Ti51Hhmu3~oJDQ;Sf9nlYTw0D$Dal&0M7lT%gO#wCS<^Xq z3+9&=<>xL#g~ItuREM+BS5#ekCl$=R`Gye~GuShKLDBLN9KVI-OY=D@xn*}17v>f% zUARnHR5qq)S!pg57LJ;_w5UvZMTVrLP{y3r!oU%iEi77Ekh`#`q_iw|*+TIpn ze8hB#a?16cf@{>Bi{_UZk3qjT{umNBh(^yZE@p%(0+fu&oxT90TS#LO(Mt-KmgU5d zmo6(P6vJu7jJSSi*Ul&#mA|aKOeE<0oGH_1ESr(5x?WneA`4xR&gLTkbIX?&t|%_d zFDopN3Je(uY>{xCVaK>`CeGgsf_zTsSZBveA!>@36)i=W#K=i&a78ZWL;fOIf?h+R znt%&1$7QbQSq*=}V{j?s39@l*aO6vi5*dRTVO*{TM4DZIytC9aER=;D0dGMM#cE=(m$m*vXjXU@o9R8UmnFqJt4<;5eNh53t@l@>aMD+=?M7dv-it``>-I13Aw zAy}N!!m{NH$`?XtY1v|DN#T+u%a#{92*vy*#RQ$(a%q>&x=ZF4Nxj0Q%bhz*Fh!lx zyGrwyEnVnbJ84qxWy3R_YqO_LoRm9q_$c??$l;f(_p@h1V$|>vqnt^zXHS?oHFw1D z%WMu;ge3e+w*F)3ajD7RqzF$*@Gtr5KkF%asw+iGH(d*ht;kbDl9u56RH@Y+?^JEW zPjLc5p|q0cUup^9-|Ki|uCHu!Ejq{EyarozY(d;trbXxYnb#PL&bG}fWYO*Omas*4kC0F) z$D(6k+}CW2jsbUHc^2IsuSFKUrz;J=S#$)F`&wbqd%0A{S!2qBmG{v*#we(W0Ma$v0W_ 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

JaxVbb{LtwW!^5EXqk!wVrqP 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 LKHd1Y-v9pZaDJ2} literal 73372 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 diff --git a/s.py b/s.py old mode 100644 new mode 100755 index 35dfefb..7997974 --- a/s.py +++ b/s.py @@ -1,3 +1,7 @@ import subprocess -p = subprocess.Popen(["echo", "what the hell"]) +p = subprocess.Popen(["grep", "f"], + stdin = subprocess.PIPE, + stdout = subprocess.PIPE) +p.stdin.write('one\ntwo\four\n') +p.communicate()[0] diff --git a/subprocess.hpp b/subprocess.hpp index 29fe9c5..58f2f6d 100755 --- a/subprocess.hpp +++ b/subprocess.hpp @@ -1,5 +1,5 @@ -#include #include +#include #include #include #include @@ -7,7 +7,7 @@ #include #include #include -#include +#include #include #include @@ -47,7 +47,7 @@ public: namespace util { - std::vector + static std::vector split(const std::string& str, const std::string& delims=" \t") { std::vector res; @@ -67,6 +67,7 @@ namespace util return res; } + static std::string join(const std::vector& vec, const std::string& sep = " ") { @@ -76,15 +77,17 @@ namespace util return res; } + static void set_clo_on_exec(int fd, bool set = true) { - int flags = fcntl(fd, F_GETFL, 0); + int flags = fcntl(fd, F_GETFD, 0); if (set) flags |= FD_CLOEXEC; else flags &= ~FD_CLOEXEC; //TODO: should check for errors - fcntl(fd, F_SETFL, flags); + fcntl(fd, F_SETFD, flags); } + static std::pair pipe_cloexec() { int pipe_fds[2]; @@ -100,6 +103,7 @@ namespace util } + static int write_n(int fd, const char* buf, size_t length) { int nwritten = 0; @@ -111,6 +115,7 @@ namespace util return nwritten; } + static int read_atmost_n(int fd, char* buf, size_t read_upto) { int rbytes = 0; @@ -133,6 +138,7 @@ namespace util return rbytes; } + static int wait_for_child_exit(int pid) { int status; @@ -152,9 +158,20 @@ namespace util // Popen Arguments -struct bufsiz { int bufsiz = 0; }; -struct defer_spawn { bool defer = false; }; -struct close_fds { bool close_all = false; }; +struct bufsize { + bufsize(int siz): bufsiz(siz) {} + int bufsiz = 0; +}; + +struct defer_spawn { + defer_spawn(bool d): defer(d) {} + bool defer = false; +}; + +struct close_fds { + close_fds(bool c): close_all(c) {} + bool close_all = false; +}; struct string_arg { @@ -192,6 +209,7 @@ enum IOTYPE { PIPE, }; + struct input { input(int fd): rd_ch_(fd) {} @@ -228,7 +246,8 @@ struct output int wr_ch_ = -1; }; -struct error { +struct error +{ error(int fd): wr_ch_(fd) {} error(const char* filename) { @@ -256,41 +275,38 @@ struct ArgumentDeducer { ArgumentDeducer(Popen* p): popen_(p) {} - template - void set_options(T&& arg) - { - set_option(std::forward(arg)); - } - - template - void set_options(T&& farg, Args&&... rem_args) - { - set_option(std::forward(farg)); - set_options(std::forward(rem_args)...); - } - void set_option(executable&& exe); - void set_option(cwd&& cwdir); - - void set_option(bufsiz&& bsiz); - + void set_option(bufsize&& bsiz); void set_option(environment&& env); - void set_option(defer_spawn&& defer); - void set_option(input&& inp); - void set_option(output&& out); - void set_option(error&& err); - void set_option(close_fds&& cfds); private: Popen* popen_ = nullptr; }; + +class Child +{ +public: + Child(Popen* p, int err_wr_pipe): + parent_(p), + err_wr_pipe_(err_wr_pipe) + {} + + void execute_child(); + +private: + // Lets call it parent even though + // technically a bit incorrect + Popen* parent_ = nullptr; + int err_wr_pipe_ = -1; +}; + }; // end namespace detail @@ -298,6 +314,7 @@ class Popen { public: friend class detail::ArgumentDeducer; + friend class detail::Child; template Popen(const std::string& cmd_args, Args&& ...args): @@ -306,14 +323,7 @@ public: vargs_ = util::split(cmd_args); init_args(std::forward(args)...); - try { - if (!defer_process_start_) execute_process(); - } catch (const std::exception& e) { - cleanup_fds(); - throw e; - } - - setup_comm_channels(); + if (!defer_process_start_) execute_process(); } template @@ -322,14 +332,7 @@ public: vargs_.insert(vargs_.end(), cmd_args.begin(), cmd_args.end()); init_args(std::forward(args)...); - try { - if (!defer_process_start_) execute_process(); - } catch (const std::exception& e) { - cleanup_fds(); - throw e; - } - - setup_comm_channels(); + if (!defer_process_start_) execute_process(); } void start_process() throw (CalledProcessError, OSError) @@ -343,23 +346,17 @@ public: assert (0); return; } - try { - execute_process(); - } catch (const std::exception& e) { - cleanup_fds(); - throw e; - } - - setup_comm_channels(); + execute_process(); } - FILE* input() { return input_; } - FILE* output() { return output_; } - FILE* error() { return error_; } + FILE* input() { return input_.get(); } + FILE* output() { return output_.get(); } + FILE* error() { return error_.get(); } private: - template - void init_args(Args&&... args); + template + void init_args(F&& farg, Args&&... args); + void init_args(); void populate_c_argv(); void execute_process() throw (CalledProcessError, OSError); void cleanup_fds(); @@ -373,9 +370,9 @@ private: std::string cwd_; std::map env_; - FILE* input_ = nullptr; - FILE* output_ = nullptr; - FILE* error_ = nullptr; + std::shared_ptr input_ = nullptr; + std::shared_ptr output_ = nullptr; + std::shared_ptr error_ = nullptr; // Pipes for communicating with child @@ -401,16 +398,16 @@ private: int child_pid_ = -1; }; -template <> void Popen::init_args() { populate_c_argv(); } -template -void Popen::init_args(Args&&... args) +template +void Popen::init_args(F&& farg, Args&&... args) { detail::ArgumentDeducer argd(this); - argd.set_options(std::forward(args)...); + argd.set_option(std::forward(farg)); + init_args(std::forward(args)...); } void Popen::populate_c_argv() @@ -423,51 +420,43 @@ void Popen::cleanup_fds() { if (write_to_child_ != -1 && read_from_parent_ != -1) { close(write_to_child_); - close(read_from_parent_); } if (write_to_parent_ != -1 && read_from_child_ != -1) { - close(write_to_parent_); close(read_from_child_); } if (err_write_ != -1 && err_read_ != -1) { - close(err_write_); close(err_read_); } } void Popen::setup_comm_channels() { - if (write_to_child_ != -1) { - input_ = fdopen(write_to_child_, "wb"); - } - if (write_to_parent_ != -1) { - output_ = fdopen(write_to_parent_, "rb"); - } - if (err_read_ != -1) { - error_ = fdopen(err_read_, "rb"); - } + if (write_to_child_ != -1) input_.reset(fdopen(write_to_child_, "wb"), fclose); + if (read_from_child_ != -1) output_.reset(fdopen(read_from_child_, "rb"), fclose); + if (err_read_ != -1) error_.reset(fdopen(err_read_, "rb"), fclose); + + auto handles = {input_.get(), output_.get(), error_.get()}; - auto handles = {input_, output_, error_}; for (auto& h : handles) { - //TODO: error checking if (h == nullptr) continue; - if (bufsiz_ == 0) + switch (bufsiz_) { + case 0: setvbuf(h, nullptr, _IONBF, BUFSIZ); - else if (bufsiz_ == 1) + break; + case 1: setvbuf(h, nullptr, _IONBF, BUFSIZ); - else + break; + default: setvbuf(h, nullptr, _IOFBF, bufsiz_); + }; } } - void Popen::execute_process() throw (CalledProcessError, OSError) { int err_rd_pipe, err_wr_pipe; - int sys_ret = -1; - std::tie(err_rd_pipe, err_wr_pipe) = util::pipe_cloexec(); if (!exe_name_.length()) { @@ -477,112 +466,58 @@ void Popen::execute_process() throw (CalledProcessError, OSError) child_pid_ = fork(); if (child_pid_ < 0) { - close (err_rd_pipe); - close (err_wr_pipe); + close(err_rd_pipe); + close(err_wr_pipe); throw OSError("fork failed", errno); } - if (child_pid_ == 0) {/* Child Part of Code */ - try { - // Close descriptors belonging to parent - if (write_to_child_ != -1) close(write_to_child_); - if (read_from_child_ != -1) close(read_from_child_); - if (err_read_ != -1) close(err_read_); - close(err_rd_pipe); - - // Make the child owned descriptors as the - // stdin, stdout and stderr for the child process - auto _dup2_ = [](int fd, int to_fd) { - if (fd == to_fd) { - // dup2 syscall does not reset the - // CLOEXEC flag if the descriptors - // provided to it are same. - // But, we need to reset the CLOEXEC - // flag as the provided descriptors - // are now going to be the standard - // input, output and error - util::set_clo_on_exec(fd, false); - } else if(fd != -1) { - int res = dup2(fd, to_fd); - if (res == -1) throw OSError("dup2 failed", errno); - } - }; - - // Create the standard streams - _dup2_(read_from_parent_, 0); // Input stream - _dup2_(write_to_parent_, 1); // Output stream - _dup2_(err_write_, 2); // Error stream - - // Close the extra sockets - if (read_from_parent_ != -1 && read_from_parent_ > 2) close(read_from_parent_); - if (write_to_parent_ != -1 && write_to_parent_ > 2) close(write_to_parent_); - if (err_write_ != -1 && err_write_ > 2) close(err_write_); - - // Close all the inherited fd's except the error write pipe - if (close_fds_) { - int max_fd = sysconf(_SC_OPEN_MAX); - - if (max_fd == -1) throw OSError("sysconf failed", errno); - - for (int i = 3; i < max_fd; i++) { - if (i == err_wr_pipe) continue; - close(i); - } - } - - // Change the working directory if provided - if (cwd_.length()) { - sys_ret = chdir(cwd_.c_str()); - if (sys_ret == -1) throw OSError("chdir failed", errno); - } - - // Replace the current image with the executable - if (env_.size()) { - for (auto& kv : env_) setenv(kv.first.c_str(), kv.second.c_str(), 1); - sys_ret = execvp(exe_name_.c_str(), cargv_.data()); - } else { - sys_ret = execvp(exe_name_.c_str(), cargv_.data()); - } - if (sys_ret == -1) throw OSError("execve failed", errno); - - } catch (const OSError& exp) { - // Just write the exception message - // TODO: Give back stack trace ? - std::string err_msg(exp.what()); - //ATTN: Can we do something on error here ? - util::write_n(err_wr_pipe, err_msg.c_str(), err_msg.length()); - close(err_wr_pipe); - } - - // Calling application would not get this - // exit failure - exit (EXIT_FAILURE); - } else { // Parent code - // Close the err_wr_pipe - // Else get stuck forever!! - close (err_wr_pipe); - // Read the error from child if at all - char err_buf[SP_MAX_ERR_BUF_SIZ] = {0,}; - int read_bytes = util::read_atmost_n(err_rd_pipe, err_buf, SP_MAX_ERR_BUF_SIZ); - + if (child_pid_ == 0) + { + // Close descriptors belonging to parent + if (write_to_child_ != -1) close(write_to_child_); + if (read_from_child_ != -1) close(read_from_child_); + if (err_read_ != -1) close(err_read_); + //Close the read end of the error pipe close(err_rd_pipe); - if (read_bytes || strlen(err_buf)) { - // Call waitpid to reap the child process - // waitpid suspends the calling process until the - // child terminates. - sys_ret = util::wait_for_child_exit(child_pid_); - // If the child could not be reaped successfully - // raise that error instead of child error - if (sys_ret == -1) throw OSError("child exit", errno); + detail::Child chld(this, err_wr_pipe); + chld.execute_child(); + } + else + { + int sys_ret = -1; + close (err_wr_pipe);// close child side of pipe, else get stuck in read below - // Throw whatever information we have about child failure - throw CalledProcessError(err_buf); + // Close child pipes + if (write_to_parent_ != -1) close(write_to_parent_); + if (read_from_parent_ != -1) close(read_from_parent_); + if (err_write_ != -1) close(err_write_); + + try { + char err_buf[SP_MAX_ERR_BUF_SIZ] = {0,}; + int read_bytes = util::read_atmost_n(err_rd_pipe, err_buf, SP_MAX_ERR_BUF_SIZ); + close(err_rd_pipe); + + if (read_bytes || strlen(err_buf)) { + // Call waitpid to reap the child process + // waitpid suspends the calling process until the + // child terminates. + sys_ret = util::wait_for_child_exit(child_pid_); + if (sys_ret == -1) throw OSError("child exit", errno); + + // Throw whatever information we have about child failure + throw CalledProcessError(err_buf); + } + } catch (std::exception& exp) { + cleanup_fds(); + throw exp; } + + // Setup the communication channels of the Popen class + setup_comm_channels(); } } - namespace detail { void ArgumentDeducer::set_option(executable&& exe) { @@ -593,7 +528,7 @@ namespace detail { popen_->cwd_ = std::move(cwdir.arg_value); } - void ArgumentDeducer::set_option(bufsiz&& bsiz) { + void ArgumentDeducer::set_option(bufsize&& bsiz) { popen_->bufsiz_ = bsiz.bufsiz; } @@ -625,6 +560,91 @@ namespace detail { } + void Child::execute_child() { + int sys_ret = -1; + try { + if (parent_->write_to_parent_ == 0) + parent_->write_to_parent_ = dup(parent_->write_to_parent_); + if (parent_->err_write_ == 0 || parent_->err_write_ == 1) + parent_->err_write_ = dup(parent_->err_write_); + + // Make the child owned descriptors as the + // stdin, stdout and stderr for the child process + auto _dup2_ = [](int fd, int to_fd) { + if (fd == to_fd) { + // dup2 syscall does not reset the + // CLOEXEC flag if the descriptors + // provided to it are same. + // But, we need to reset the CLOEXEC + // flag as the provided descriptors + // are now going to be the standard + // input, output and error + util::set_clo_on_exec(fd, false); + } else if(fd != -1) { + int res = dup2(fd, to_fd); + if (res == -1) throw OSError("dup2 failed", errno); + } + }; + + // Create the standard streams + _dup2_(parent_->read_from_parent_, 0); // Input stream + _dup2_(parent_->write_to_parent_, 1); // Output stream + _dup2_(parent_->err_write_, 2); // Error stream + + // Close the duped descriptors + if (parent_->read_from_parent_ != -1 && parent_->read_from_parent_ > 2) + close(parent_->read_from_parent_); + + if (parent_->write_to_parent_ != -1 && parent_->write_to_parent_ > 2) + close(parent_->write_to_parent_); + + if (parent_->err_write_ != -1 && parent_->err_write_ > 2) + close(parent_->err_write_); + + // Close all the inherited fd's except the error write pipe + if (parent_->close_fds_) { + int max_fd = sysconf(_SC_OPEN_MAX); + if (max_fd == -1) throw OSError("sysconf failed", errno); + + for (int i = 3; i < max_fd; i++) { + if (i == err_wr_pipe_) continue; + close(i); + } + } + + // Change the working directory if provided + if (parent_->cwd_.length()) { + sys_ret = chdir(parent_->cwd_.c_str()); + if (sys_ret == -1) throw OSError("chdir failed", errno); + } + + // Replace the current image with the executable + if (parent_->env_.size()) { + for (auto& kv : parent_->env_) { + setenv(kv.first.c_str(), kv.second.c_str(), 1); + } + sys_ret = execvp(parent_->exe_name_.c_str(), parent_->cargv_.data()); + } else { + sys_ret = execvp(parent_->exe_name_.c_str(), parent_->cargv_.data()); + } + + if (sys_ret == -1) throw OSError("execve failed", errno); + + } catch (const OSError& exp) { + // Just write the exception message + // TODO: Give back stack trace ? + std::string err_msg(exp.what()); + //ATTN: Can we do something on error here ? + util::write_n(err_wr_pipe_, err_msg.c_str(), err_msg.length()); + } + + // Calling application would not get this + // exit failure + exit (EXIT_FAILURE); + + } + + }; // end namespace detail