Commit 4af3040b authored by Yedidya Feldblum's avatar Yedidya Feldblum Committed by Facebook Github Bot

Let ProcessReturnCode be publicly constructible

Summary:
[Folly] Let `ProcessReturnCode` be publicly constructible.

Via provided constructor functions, which limit how it may be constructed so that it is only constructible into a valid state.

Differential Revision: D5898739

fbshipit-source-id: 7490018adfc39408b4290248ef1220e8fd0238cb
parent 91da2e5a
...@@ -51,6 +51,14 @@ constexpr int kChildFailure = 126; ...@@ -51,6 +51,14 @@ constexpr int kChildFailure = 126;
namespace folly { 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 ProcessReturnCode::ProcessReturnCode(ProcessReturnCode&& p) noexcept
: rawStatus_(p.rawStatus_) { : rawStatus_(p.rawStatus_) {
p.rawStatus_ = ProcessReturnCode::RV_NOT_STARTED; p.rawStatus_ = ProcessReturnCode::RV_NOT_STARTED;
...@@ -68,8 +76,7 @@ ProcessReturnCode::State ProcessReturnCode::state() const { ...@@ -68,8 +76,7 @@ ProcessReturnCode::State ProcessReturnCode::state() const {
if (rawStatus_ == RV_RUNNING) return RUNNING; if (rawStatus_ == RV_RUNNING) return RUNNING;
if (WIFEXITED(rawStatus_)) return EXITED; if (WIFEXITED(rawStatus_)) return EXITED;
if (WIFSIGNALED(rawStatus_)) return KILLED; if (WIFSIGNALED(rawStatus_)) return KILLED;
throw std::runtime_error(to<std::string>( assume_unreachable();
"Invalid ProcessReturnCode: ", rawStatus_));
} }
void ProcessReturnCode::enforce(State expected) const { void ProcessReturnCode::enforce(State expected) const {
...@@ -427,7 +434,7 @@ void Subprocess::spawnInternal( ...@@ -427,7 +434,7 @@ void Subprocess::spawnInternal(
// child has exited and can be immediately waited for. In all other cases, // child has exited and can be immediately waited for. In all other cases,
// we have no way of cleaning up the child. // we have no way of cleaning up the child.
pid_ = pid; pid_ = pid;
returnCode_ = ProcessReturnCode(RV_RUNNING); returnCode_ = ProcessReturnCode::makeRunning();
} }
int Subprocess::prepareChild(const Options& options, int Subprocess::prepareChild(const Options& options,
...@@ -562,7 +569,7 @@ ProcessReturnCode Subprocess::poll(struct rusage* ru) { ...@@ -562,7 +569,7 @@ ProcessReturnCode Subprocess::poll(struct rusage* ru) {
if (found != 0) { if (found != 0) {
// Though the child process had quit, this call does not close the pipes // Though the child process had quit, this call does not close the pipes
// since its descendants may still be using them. // since its descendants may still be using them.
returnCode_ = ProcessReturnCode(status); returnCode_ = ProcessReturnCode::make(status);
pid_ = -1; pid_ = -1;
} }
return returnCode_; return returnCode_;
...@@ -590,7 +597,7 @@ ProcessReturnCode Subprocess::wait() { ...@@ -590,7 +597,7 @@ ProcessReturnCode Subprocess::wait() {
// Though the child process had quit, this call does not close the pipes // Though the child process had quit, this call does not close the pipes
// since its descendants may still be using them. // since its descendants may still be using them.
DCHECK_EQ(found, pid_); DCHECK_EQ(found, pid_);
returnCode_ = ProcessReturnCode(status); returnCode_ = ProcessReturnCode::make(status);
pid_ = -1; pid_ = -1;
return returnCode_; return returnCode_;
} }
......
...@@ -127,7 +127,6 @@ namespace folly { ...@@ -127,7 +127,6 @@ namespace folly {
*/ */
class Subprocess; class Subprocess;
class ProcessReturnCode { class ProcessReturnCode {
friend class Subprocess;
public: public:
enum State { enum State {
// Subprocess starts in the constructor, so this state designates only // Subprocess starts in the constructor, so this state designates only
...@@ -135,12 +134,22 @@ class ProcessReturnCode { ...@@ -135,12 +134,22 @@ class ProcessReturnCode {
NOT_STARTED, NOT_STARTED,
RUNNING, RUNNING,
EXITED, EXITED,
KILLED KILLED,
}; };
static ProcessReturnCode makeNotStarted() {
return ProcessReturnCode(RV_NOT_STARTED);
}
static ProcessReturnCode makeRunning() {
return ProcessReturnCode(RV_RUNNING);
}
static ProcessReturnCode make(int status);
// Default-initialized for convenience. Subprocess::returnCode() will // Default-initialized for convenience. Subprocess::returnCode() will
// never produce this value. // never produce this value.
ProcessReturnCode() : ProcessReturnCode(RV_NOT_STARTED) {} ProcessReturnCode() : rawStatus_(RV_NOT_STARTED) {}
// Trivially copyable // Trivially copyable
ProcessReturnCode(const ProcessReturnCode& p) = default; ProcessReturnCode(const ProcessReturnCode& p) = default;
...@@ -813,9 +822,6 @@ class Subprocess { ...@@ -813,9 +822,6 @@ class Subprocess {
std::vector<ChildPipe> takeOwnershipOfPipes(); std::vector<ChildPipe> takeOwnershipOfPipes();
private: private:
static const int RV_RUNNING = ProcessReturnCode::RV_RUNNING;
static const int RV_NOT_STARTED = ProcessReturnCode::RV_NOT_STARTED;
// spawn() sets up a pipe to read errors from the child, // spawn() sets up a pipe to read errors from the child,
// then calls spawnInternal() to do the bulk of the work. Once // then calls spawnInternal() to do the bulk of the work. Once
// spawnInternal() returns it reads the error pipe to see if the child // spawnInternal() returns it reads the error pipe to see if the child
...@@ -851,7 +857,7 @@ class Subprocess { ...@@ -851,7 +857,7 @@ class Subprocess {
size_t findByChildFd(const int childFd) const; size_t findByChildFd(const int childFd) const;
pid_t pid_{-1}; pid_t pid_{-1};
ProcessReturnCode returnCode_{RV_NOT_STARTED}; ProcessReturnCode returnCode_;
/** /**
* Represents a pipe between this process, and the child process (or its * Represents a pipe between this process, and the child process (or its
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment