diff --git a/subprocess.hpp b/subprocess.hpp index 1e68096..c4bcbba 100755 --- a/subprocess.hpp +++ b/subprocess.hpp @@ -42,6 +42,7 @@ Documentation for C++ subprocessing libraray. #include #include #include +#include #include #include #include @@ -53,7 +54,7 @@ extern "C" { #include #include #include - #include + #include #include } @@ -67,7 +68,7 @@ extern "C" { * library: OSError and CalledProcessError * * 2. Popen Class - * This is the main class the users will deal with. It + * This is the main class the users will deal with. It * provides with all the API's to deal with processes. * * 3. Util namespace @@ -89,11 +90,11 @@ static const size_t SP_MAX_ERR_BUF_SIZ = 1024; // Default buffer capcity for OutBuffer and ErrBuffer. // If the data exceeds this capacity, the buffer size is grown // by 1.5 times its previous capacity -static const size_t DEFAULT_BUF_CAP_BYTES = 8192; +static const size_t DEFAULT_BUF_CAP_BYTES = 8192; /*----------------------------------------------- - * EXCEPTION CLASSES + * EXCEPTION CLASSES *----------------------------------------------- */ @@ -139,7 +140,7 @@ namespace util /*! * Function: split * Parameters: - * [in] str : Input string which needs to be split based upon the + * [in] str : Input string which needs to be split based upon the * delimiters provided. * [in] deleims : Delimiter characters based upon which the string needs * to be split. Default constructed to ' '(space) and '\t'(tab) @@ -258,7 +259,7 @@ namespace util /*! * Function: read_atmost_n - * Reads at the most `read_upto` bytes from the + * Reads at the most `read_upto` bytes from the * file descriptor `fd` before returning. * Parameters: * [in] fd : The file descriptor from which it needs to read. @@ -355,7 +356,7 @@ namespace util int status = 0; int ret = -1; while (1) { - ret = waitpid(pid, &status, WNOHANG); + ret = waitpid(pid, &status, WNOHANG); if (ret == -1) break; if (ret == 0) continue; return std::make_pair(ret, status); @@ -379,7 +380,7 @@ namespace util * streams of the child process. * Default value is 0. */ -struct bufsize { +struct bufsize { bufsize(int siz): bufsiz(siz) {} int bufsiz = 0; }; @@ -389,7 +390,7 @@ struct bufsize { * till `Popen::start_process` API is called. * Default value is false. */ -struct defer_spawn { +struct defer_spawn { defer_spawn(bool d): defer(d) {} bool defer = false; }; @@ -403,7 +404,7 @@ struct defer_spawn { * * Default value is false. */ -struct close_fds { +struct close_fds { close_fds(bool c): close_all(c) {} bool close_all = false; }; @@ -438,7 +439,7 @@ struct string_arg /*! * Option to specify the executable name seperately * from the args sequence. - * In this case the cmd args must only contain the + * In this case the cmd args must only contain the * options required for this executable. * * Eg: executable{"ls"} @@ -480,7 +481,7 @@ struct environment /*! * Used for redirecting input/output/error */ -enum IOTYPE { +enum IOTYPE { STDOUT = 1, STDERR, PIPE, @@ -568,7 +569,7 @@ struct error error(FILE* fp):error(fileno(fp)) { assert(fp); } error(const char* filename) { - int fd = open(filename, O_APPEND | O_CREAT | O_RDWR, 0640); + int fd = open(filename, O_APPEND | O_CREAT | O_RDWR, 0640); if (fd == -1) throw OSError("File not found: ", errno); wr_ch_ = fd; } @@ -593,7 +594,7 @@ struct error // ATTN: Can be used only to execute functions with no // arguments and returning void. // Could have used more efficient methods, ofcourse, but -// that wont yield me the consistent syntax which I am +// that wont yield me the consistent syntax which I am // aiming for. If you know, then please do let me know. class preexec_func @@ -711,11 +712,11 @@ struct has_type> { //---- /*! - * A helper class to Popen class for setting + * A helper class to Popen class for setting * options as provided in the Popen constructor * or in check_ouput arguments. * This design allows us to _not_ have any fixed position - * to any arguments and specify them in a way similar to what + * to any arguments and specify them in a way similar to what * can be done in python. */ struct ArgumentDeducer @@ -755,7 +756,7 @@ public: void execute_child(); private: - // Lets call it parent even though + // Lets call it parent even though // technically a bit incorrect Popen* parent_ = nullptr; int err_wr_pipe_ = -1; @@ -803,7 +804,7 @@ private: * This is a helper class to Popen. * It takes care of management of all the file descriptors * and file pointers. - * It dispatches of the communication aspects to the + * It dispatches of the communication aspects to the * Communication class. * Read through the data members to understand about the * various file descriptors used. @@ -935,7 +936,7 @@ public: friend class detail::Child; template - Popen(const std::string& cmd_args, Args&& ...args): + Popen(const std::string& cmd_args, Args&& ...args): args_(cmd_args) { vargs_ = util::split(cmd_args); @@ -977,7 +978,7 @@ public: void set_err_buf_cap(size_t cap) { stream_.set_err_buf_cap(cap); } - int send(const char* msg, size_t length) + int send(const char* msg, size_t length) { return stream_.send(msg, length); } int send(const std::vector& msg) @@ -1150,6 +1151,11 @@ void Popen::execute_process() throw (CalledProcessError, OSError) } exe_name_ = vargs_[0]; + std::signal(SIGCHLD, [](int sig){ + int status; + waitpid(-1, &status, WNOHANG); + }); + child_pid_ = fork(); if (child_pid_ < 0) { @@ -1170,8 +1176,8 @@ void Popen::execute_process() throw (CalledProcessError, OSError) detail::Child chld(this, err_wr_pipe); chld.execute_child(); - } - else + } + else { int sys_ret = -1; close (err_wr_pipe);// close child side of pipe, else get stuck in read below @@ -1182,8 +1188,8 @@ void Popen::execute_process() throw (CalledProcessError, OSError) char err_buf[SP_MAX_ERR_BUF_SIZ] = {0,}; int read_bytes = util::read_atmost_n( - err_rd_pipe, - err_buf, + err_rd_pipe, + err_buf, SP_MAX_ERR_BUF_SIZ); close(err_rd_pipe); @@ -1301,13 +1307,13 @@ namespace detail { _dup2_(stream.err_write_, 2); // Error stream // Close the duped descriptors - if (stream.read_from_parent_ != -1 && stream.read_from_parent_ > 2) + if (stream.read_from_parent_ != -1 && stream.read_from_parent_ > 2) close(stream.read_from_parent_); - if (stream.write_to_parent_ != -1 && stream.write_to_parent_ > 2) + if (stream.write_to_parent_ != -1 && stream.write_to_parent_ > 2) close(stream.write_to_parent_); - if (stream.err_write_ != -1 && stream.err_write_ > 2) + if (stream.err_write_ != -1 && stream.err_write_ > 2) close(stream.err_write_); // Close all the inherited fd's except the error write pipe @@ -1444,7 +1450,7 @@ namespace detail { int rbytes = util::read_atmost_n( fileno(stream_->error()), - ebuf.buf.data(), + ebuf.buf.data(), ebuf.buf.size()); if (rbytes == -1) { @@ -1538,12 +1544,12 @@ namespace detail { return Popen(std::forward(farg), std::forward(args)...).wait(); } - + void pipeline_impl(std::vector& cmds) { /* EMPTY IMPL */ } template - void pipeline_impl(std::vector& cmds, - const std::string& cmd, + void pipeline_impl(std::vector& cmds, + const std::string& cmd, Args&&... args) { if (cmds.size() == 0) { @@ -1565,7 +1571,7 @@ namespace detail /*! * Run the command with arguments and wait for it to complete. - * The parameters passed to the argument are exactly the same + * The parameters passed to the argument are exactly the same * one would use for Popen constructors. */ template