diff options
-rw-r--r-- | libadhocutil/processPipes.cpp | 70 | ||||
-rw-r--r-- | libadhocutil/processPipes.h | 3 |
2 files changed, 36 insertions, 37 deletions
diff --git a/libadhocutil/processPipes.cpp b/libadhocutil/processPipes.cpp index 229c9d2..511f415 100644 --- a/libadhocutil/processPipes.cpp +++ b/libadhocutil/processPipes.cpp @@ -4,6 +4,7 @@ #include <string.h> #include <sys/resource.h> #include <stdexcept> +#include "scopeExit.h" namespace AdHoc { namespace System { @@ -14,47 +15,36 @@ ProcessPipes::ProcessPipes(const std::vector<std::string> & args, bool i, bool o error(-1) { int ipipes[2], opipes[2], epipes[2]; + ScopeExit tidyUp; if (i) { if (pipe(ipipes)) { throw std::runtime_error("Failed to create stdin pipe"); } + tidyUp.onFailure.push_back([ipipes] { + close(ipipes[0]); + close(ipipes[1]); + }); } if (o) { if (pipe(opipes)) { - if (i) { - close(ipipes[0]); - close(ipipes[1]); - } throw std::runtime_error("Failed to create stdout pipe"); } + tidyUp.onFailure.push_back([opipes] { + close(opipes[0]); + close(opipes[1]); + }); } if (e) { if (pipe(epipes)) { - if (i) { - close(ipipes[0]); - close(ipipes[1]); - } - if (o) { - close(opipes[0]); - close(opipes[1]); - } throw std::runtime_error("Failed to create stderr pipe"); } + tidyUp.onFailure.push_back([epipes] { + close(epipes[0]); + close(epipes[1]); + }); } switch (child = fork()) { case -1: // fail - if (i) { - close(ipipes[0]); - close(ipipes[1]); - } - if (o) { - close(opipes[0]); - close(opipes[1]); - } - if (e) { - close(epipes[0]); - close(epipes[1]); - } throw std::runtime_error("Failed to fork"); default: // parent if (i) { @@ -71,8 +61,6 @@ ProcessPipes::ProcessPipes(const std::vector<std::string> & args, bool i, bool o } break; case 0: // in child - rlimit lim; - getrlimit(RLIMIT_NOFILE, &lim); if (i) { close(ipipes[1]); dup2(ipipes[0], 0); @@ -85,17 +73,7 @@ ProcessPipes::ProcessPipes(const std::vector<std::string> & args, bool i, bool o close(epipes[0]); dup2(epipes[1], 2); } - std::vector<struct pollfd> fds; - fds.reserve(lim.rlim_max); - for (int n = 3; n < (int)lim.rlim_max; n += 1) { - fds.push_back({n, 0, 0}); - } - poll(&fds.front(), fds.size(), 0); - for(const auto & pfd : fds) { - if (!(pfd.revents & POLLNVAL)) { - close(pfd.fd); - } - } + closeAllOpenFiles(); char * buf[100]; char ** w = &buf[0]; for (const auto & p : args) { @@ -139,6 +117,24 @@ ProcessPipes::pid() const return child; } +void +ProcessPipes::closeAllOpenFiles() +{ + rlimit lim; + getrlimit(RLIMIT_NOFILE, &lim); + std::vector<struct pollfd> fds; + fds.reserve(lim.rlim_max); + for (int n = 3; n < (int)lim.rlim_max; n += 1) { + fds.push_back({n, 0, 0}); + } + poll(&fds.front(), fds.size(), 0); + for(const auto & pfd : fds) { + if (!(pfd.revents & POLLNVAL)) { + close(pfd.fd); + } + } +} + } } diff --git a/libadhocutil/processPipes.h b/libadhocutil/processPipes.h index 195d8e9..bbf7508 100644 --- a/libadhocutil/processPipes.h +++ b/libadhocutil/processPipes.h @@ -31,6 +31,9 @@ class DLL_PUBLIC ProcessPipes { /** Process id of child. */ pid_t pid() const; + /** Close all open file handles as determined by rlimit and poll. */ + static void closeAllOpenFiles(); + private: ProcessPipes(const ProcessPipes &) = delete; void operator=(const ProcessPipes &) = delete; |