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
+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::ProcessReturnCode(ProcessReturnCode&& p) noexcept
: rawStatus_(p.rawStatus_) {
p.rawStatus_ = ProcessReturnCode::RV_NOT_STARTED;
if (rawStatus_ == RV_RUNNING) return RUNNING;
if (WIFEXITED(rawStatus_)) return EXITED;
if (WIFSIGNALED(rawStatus_)) return KILLED;
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_));
}
void ProcessReturnCode::enforce(State expected) const {
}
void ProcessReturnCode::enforce(State expected) const {
// child has exited and can be immediately waited for. In all other cases,
// we have no way of cleaning up the child.
pid_ = pid;
// 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,
}
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.
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_;
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_);
// 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_;
}
pid_ = -1;
return returnCode_;
}
*/
class Subprocess;
class ProcessReturnCode {
*/
class Subprocess;
class ProcessReturnCode {
- friend class Subprocess;
public:
enum State {
// Subprocess starts in the constructor, so this state designates only
public:
enum State {
// Subprocess starts in the constructor, so this state designates only
NOT_STARTED,
RUNNING,
EXITED,
NOT_STARTED,
RUNNING,
EXITED,
+ 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
// never produce this value.
// Default-initialized for convenience. Subprocess::returnCode() will
// never produce this value.
- ProcessReturnCode() : ProcessReturnCode(RV_NOT_STARTED) {}
+ ProcessReturnCode() : rawStatus_(RV_NOT_STARTED) {}
// Trivially copyable
ProcessReturnCode(const ProcessReturnCode& p) = default;
// Trivially copyable
ProcessReturnCode(const ProcessReturnCode& p) = default;
std::vector<ChildPipe> takeOwnershipOfPipes();
private:
std::vector<ChildPipe> takeOwnershipOfPipes();
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,
// then calls spawnInternal() to do the bulk of the work. Once
// spawnInternal() returns it reads the error pipe to see if the child
// spawn() sets up a pipe to read errors from the child,
// then calls spawnInternal() to do the bulk of the work. Once
// spawnInternal() returns it reads the error pipe to see if the child
size_t findByChildFd(const int childFd) const;
pid_t pid_{-1};
size_t findByChildFd(const int childFd) const;
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