friend class Subprocess;
public:
enum State {
+ // Subprocess starts in the constructor, so this state designates only
+ // default-initialized or moved-out ProcessReturnCodes.
NOT_STARTED,
RUNNING,
EXITED,
KILLED
};
+ // Default-initialized for convenience. Subprocess::returnCode() will
+ // never produce this value.
+ ProcessReturnCode() : ProcessReturnCode(RV_NOT_STARTED) {}
+
// Trivially copyable
ProcessReturnCode(const ProcessReturnCode& p) = default;
ProcessReturnCode& operator=(const ProcessReturnCode& p) = default;
class CalledProcessError : public SubprocessError {
public:
explicit CalledProcessError(ProcessReturnCode rc);
- ~CalledProcessError() throw() { }
+ ~CalledProcessError() throw() = default;
const char* what() const throw() FOLLY_OVERRIDE { return what_.c_str(); }
ProcessReturnCode returnCode() const { return returnCode_; }
private:
class SubprocessSpawnError : public SubprocessError {
public:
SubprocessSpawnError(const char* executable, int errCode, int errnoValue);
- ~SubprocessSpawnError() throw() {}
+ ~SubprocessSpawnError() throw() = default;
const char* what() const throw() FOLLY_OVERRIDE { return what_.c_str(); }
int errnoValue() const { return errnoValue_; }
ProcessReturnCode returnCode() const { return returnCode_; }
/**
- * Poll the child's status and return it, return -1 if the process
- * is still running. NOTE that it is illegal to call poll again after
- * poll indicated that the process has terminated, or to call poll on a
- * process that hasn't been successfully started (the constructor threw an
- * exception).
+ * Poll the child's status and return it. Return the exit status if the
+ * subprocess had quit, or RUNNING otherwise. Throws an std::logic_error
+ * if called on a Subprocess whose status is no longer RUNNING. No other
+ * exceptions are possible. Aborts on egregious violations of contract,
+ * e.g. if you wait for the underlying process without going through this
+ * Subprocess instance.
*/
ProcessReturnCode poll();
bool pollChecked();
/**
- * Wait for the process to terminate and return its status.
- * Similarly to poll, it is illegal to call wait after the process
- * has already been reaped or if the process has not successfully started.
+ * Wait for the process to terminate and return its status. Like poll(),
+ * the only exception this can throw is std::logic_error if you call this
+ * on a Subprocess whose status is RUNNING. Aborts on egregious
+ * violations of contract, like an out-of-band waitpid(p.pid(), 0, 0).
*/
ProcessReturnCode wait();
* No, you may NOT call this from a communicate() callback.
*/
struct ChildPipe {
+ ChildPipe(int fd, folly::File&& ppe) : childFd(fd), pipe(std::move(ppe)) {}
int childFd;
folly::File pipe; // Owns the parent FD
};