#include <glog/logging.h>
-#include <folly/Assume.h>
#include <folly/Conv.h>
#include <folly/Exception.h>
#include <folly/ScopeGuard.h>
-#include <folly/Shell.h>
#include <folly/String.h>
#include <folly/io/Cursor.h>
+#include <folly/lang/Assume.h>
#include <folly/portability/Sockets.h>
#include <folly/portability/Stdlib.h>
#include <folly/portability/SysSyscall.h>
#include <folly/portability/Unistd.h>
+#include <folly/system/Shell.h>
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<std::string>("Invalid ProcessReturnCode: ", status));
+ }
+ return ProcessReturnCode(status);
+}
+
ProcessReturnCode::ProcessReturnCode(ProcessReturnCode&& p) noexcept
: rawStatus_(p.rawStatus_) {
p.rawStatus_ = ProcessReturnCode::RV_NOT_STARTED;
}
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<std::string>(
- "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 {
}
}
-} // namespace
+} // namespace
Subprocess::Options& Subprocess::Options::fd(int fd, int action) {
if (action == Subprocess::PIPE) {
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);
}
_exit(errCode);
}
-} // namespace
+} // namespace
void Subprocess::setAllNonBlocking() {
for (auto& p : pipes_) {
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
// 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,
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_;
// 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_;
}
}
}
-} // namespace
+} // namespace
std::pair<std::string, std::string> Subprocess::communicate(
StringPiece input) {
Initializer initializer;
-} // namespace
+} // namespace
-} // namespace folly
+} // namespace folly