#include "Process.hpp"
+#include "error.hpp"
+
#ifdef _WIN32
# include <tchar.h>
# include <windows.h>
argv[args.size()] = nullptr;
if (pipe(fd_in) != 0) {
- throw runtime_error("failed to open pipe for child process' stdin");
+ throw SysError("failed to open pipe for child process' stdin");
}
if (pipe(fd_out) != 0) {
- throw runtime_error("failed to open pipe for child process' stdout");
+ throw SysError("failed to open pipe for child process' stdout");
}
if (pipe(fd_err) != 0) {
- throw runtime_error("failed to open pipe for child process' stderr");
+ throw SysError("failed to open pipe for child process' stderr");
}
pid = fork();
if (pid == -1) {
- throw runtime_error("fork");
+ throw SysError("fork");
} else if (pid == 0) {
if (dup2(fd_in[0], STDIN_FILENO) == -1) {
if (errno == EAGAIN) {
return 0;
} else {
- throw runtime_error("failed to write to child process' input stream");
+ throw SysError("failed to write to child process' input stream");
}
}
return written;
if (errno == EAGAIN) {
return 0;
} else {
- throw runtime_error("failed to read from child process' output stream");
+ throw SysError("failed to read from child process' output stream");
}
}
return ret;
if (errno == EAGAIN) {
return 0;
} else {
- throw runtime_error("failed to read from child process' error stream");
+ throw SysError("failed to read from child process' error stream");
}
}
return ret;
#else
if (kill(pid, SIGTERM) == -1) {
#endif
- throw runtime_error("failed to terminate child process");
+ throw SysError("failed to terminate child process");
}
}
int status;
int result = waitpid(pid, &status, 0);
if (result == -1) {
- throw runtime_error("error waiting on child process");
+ throw SysError("error waiting on child process");
+ }
+ if (result != pid) {
+ // should in theory only happen with WNOHANG set
+ continue;
}
- if (result == pid && WIFEXITED(status)) {
+ if (WIFEXITED(status)) {
+ // autonomous termination
return WEXITSTATUS(status);
}
- // otherwise, child probably signalled, which we don't care
- // about (please don't tell youth welfare), so try again
+ if (WIFSIGNALED(status)) {
+ // signalled termination
+ return WTERMSIG(status);
+ }
+ // otherwise, child probably signalled stop/continue, which we
+ // don't care about (please don't tell youth welfare), so try again
}
#endif
}