+void Process::Impl::Terminate() {
+ if (joined) {
+ // can only terminate once
+ return;
+ }
+#ifdef _WIN32
+ if (!TerminateProcess(pi.hProcess, -1)) {
+#else
+ if (kill(pid, SIGTERM) == -1) {
+#endif
+ throw SysError("failed to terminate child process");
+ }
+}
+
+bool Process::Impl::Terminated() {
+ if (joined) {
+ return true;
+ }
+#ifdef _WIN32
+ DWORD exit_code;
+ GetExitCodeProcess(pi.hProcess, &exit_code);
+ if (exit_code == STILL_ACTIVE) {
+ return false;
+ } else {
+ CloseHandle(pi.hProcess);
+ CloseHandle(pi.hThread);
+ status = exit_code;
+ joined = true;
+ return true;
+ }
+#else
+ int stat;
+ int result = waitpid(pid, &stat, WNOHANG);
+ if (result == -1) {
+ throw SysError("error polling child process");
+ } else if (result == 0) {
+ return false;
+ } else if (result == pid) {
+ // child just exited, reap
+ if (WIFEXITED(stat)) {
+ // autonomous termination
+ status = WEXITSTATUS(stat);
+ } else if (WIFSIGNALED(stat)) {
+ // signalled termination
+ status = WTERMSIG(stat);
+ }
+ joined = true;
+ return true;
+ } else {
+ throw runtime_error("bogus return value of waitpid");
+ }
+#endif
+}
+
+int Process::Impl::Join() {
+ if (joined) {
+ // can only join once
+ return status;
+ }
+#ifdef _WIN32