X-Git-Url: http://plrg.eecs.uci.edu/git/?a=blobdiff_plain;f=folly%2FSubprocess.cpp;h=7fb038b2dd198f4f1a197d9385b1dda704291168;hb=b92bbedce7866bf3760863604e1af1e8e42db24a;hp=b2d9cca0d21c05385298052f45fb6f56dd2e3494;hpb=31751bbfd5578b5164bc4ed5f1e6d84d87d8a736;p=folly.git diff --git a/folly/Subprocess.cpp b/folly/Subprocess.cpp index b2d9cca0..7fb038b2 100644 --- a/folly/Subprocess.cpp +++ b/folly/Subprocess.cpp @@ -25,8 +25,8 @@ #endif #include -#include #include +#include #include #include @@ -34,23 +34,31 @@ #include -#include #include #include #include -#include #include #include +#include #include #include #include #include +#include constexpr int kExecFailure = 127; constexpr int kChildFailure = 126; namespace folly { +ProcessReturnCode ProcessReturnCode::make(int status) { + if (!WIFEXITED(status) && !WIFSIGNALED(status)) { + throw std::runtime_error( + to("Invalid ProcessReturnCode: ", status)); + } + return ProcessReturnCode(status); +} + ProcessReturnCode::ProcessReturnCode(ProcessReturnCode&& p) noexcept : rawStatus_(p.rawStatus_) { p.rawStatus_ = ProcessReturnCode::RV_NOT_STARTED; @@ -64,12 +72,19 @@ ProcessReturnCode& ProcessReturnCode::operator=(ProcessReturnCode&& p) } ProcessReturnCode::State ProcessReturnCode::state() const { - if (rawStatus_ == RV_NOT_STARTED) return NOT_STARTED; - if (rawStatus_ == RV_RUNNING) return RUNNING; - if (WIFEXITED(rawStatus_)) return EXITED; - if (WIFSIGNALED(rawStatus_)) return KILLED; - throw std::runtime_error(to( - "Invalid ProcessReturnCode: ", rawStatus_)); + if (rawStatus_ == RV_NOT_STARTED) { + return NOT_STARTED; + } + if (rawStatus_ == RV_RUNNING) { + return RUNNING; + } + if (WIFEXITED(rawStatus_)) { + return EXITED; + } + if (WIFSIGNALED(rawStatus_)) { + return KILLED; + } + assume_unreachable(); } void ProcessReturnCode::enforce(State expected) const { @@ -112,20 +127,25 @@ std::string ProcessReturnCode::str() const { } CalledProcessError::CalledProcessError(ProcessReturnCode rc) - : returnCode_(rc), - what_(returnCode_.str()) { -} + : SubprocessError(rc.str()), returnCode_(rc) {} -SubprocessSpawnError::SubprocessSpawnError(const char* executable, - int errCode, - int errnoValue) - : errnoValue_(errnoValue), - what_(to(errCode == kExecFailure ? - "failed to execute " : - "error preparing to execute ", - executable, ": ", errnoStr(errnoValue))) { +static inline std::string toSubprocessSpawnErrorMessage( + char const* executable, + int errCode, + int errnoValue) { + auto prefix = errCode == kExecFailure ? "failed to execute " + : "error preparing to execute "; + return to(prefix, executable, ": ", errnoStr(errnoValue)); } +SubprocessSpawnError::SubprocessSpawnError( + const char* executable, + int errCode, + int errnoValue) + : SubprocessError( + toSubprocessSpawnErrorMessage(executable, errCode, errnoValue)), + errnoValue_(errnoValue) {} + namespace { // Copy pointers to the given strings in a format suitable for posix_spawn @@ -146,7 +166,7 @@ void checkStatus(ProcessReturnCode returnCode) { } } -} // namespace +} // namespace Subprocess::Options& Subprocess::Options::fd(int fd, int action) { if (action == Subprocess::PIPE) { @@ -173,7 +193,9 @@ Subprocess::Subprocess( if (argv.empty()) { throw std::invalid_argument("argv must not be empty"); } - if (!executable) executable = argv[0].c_str(); + if (!executable) { + executable = argv[0].c_str(); + } spawn(cloneStrings(argv), executable, options, env); } @@ -210,7 +232,7 @@ struct ChildErrorInfo { _exit(errCode); } -} // namespace +} // namespace void Subprocess::setAllNonBlocking() { for (auto& p : pipes_) { @@ -331,10 +353,10 @@ void Subprocess::spawnInternal( int cfd; if (p.second == PIPE_IN) { // Child gets reading end - pipe.pipe = folly::File(fds[1], /*owns_fd=*/ true); + pipe.pipe = folly::File(fds[1], /*ownsFd=*/true); cfd = fds[0]; } else { - pipe.pipe = folly::File(fds[0], /*owns_fd=*/ true); + pipe.pipe = folly::File(fds[0], /*ownsFd=*/true); cfd = fds[1]; } p.second = cfd; // ensure it gets dup2()ed @@ -422,7 +444,7 @@ void Subprocess::spawnInternal( // child has exited and can be immediately waited for. In all other cases, // we have no way of cleaning up the child. pid_ = pid; - returnCode_ = ProcessReturnCode(RV_RUNNING); + returnCode_ = ProcessReturnCode::makeRunning(); } int Subprocess::prepareChild(const Options& options, @@ -557,7 +579,7 @@ ProcessReturnCode Subprocess::poll(struct rusage* ru) { if (found != 0) { // Though the child process had quit, this call does not close the pipes // since its descendants may still be using them. - returnCode_ = ProcessReturnCode(status); + returnCode_ = ProcessReturnCode::make(status); pid_ = -1; } return returnCode_; @@ -585,7 +607,7 @@ ProcessReturnCode Subprocess::wait() { // Though the child process had quit, this call does not close the pipes // since its descendants may still be using them. DCHECK_EQ(found, pid_); - returnCode_ = ProcessReturnCode(status); + returnCode_ = ProcessReturnCode::make(status); pid_ = -1; return returnCode_; } @@ -665,7 +687,7 @@ bool discardRead(int fd) { } } -} // namespace +} // namespace std::pair Subprocess::communicate( StringPiece input) { @@ -853,6 +875,6 @@ class Initializer { Initializer initializer; -} // namespace +} // namespace -} // namespace folly +} // namespace folly