Revert "OS X EINVAL compatibility for waitpid"

This reverts commit 628db65504.
It was meant for the major branch.
This commit is contained in:
Kurtis Rader 2017-08-13 15:25:29 -07:00
parent 1bbd288f86
commit a3863b22a7
2 changed files with 7 additions and 25 deletions

View File

@ -1163,14 +1163,7 @@ void exec_job(parser_t &parser, job_t *j) {
//but we only need to call set_child_group for the first process in the group. //but we only need to call set_child_group for the first process in the group.
//If needs_keepalive is set, this has already been called for the keepalive process //If needs_keepalive is set, this has already been called for the keepalive process
pid_t pid_status{}; pid_t pid_status{};
int result; if (waitpid(p->pid, &pid_status, WUNTRACED) == -1) {
while ((result = waitpid(p->pid, &pid_status, WUNTRACED)) == -1 && errno == EINTR) {
//This could be a superfluous interrupt or Ctrl+C at the terminal
//In all cases, it is OK to retry since the forking code above is specifically designed
//to never, ever hang/block in a child process before the SIGSTOP call is reached.
continue;
}
if (result == -1) {
exec_error = true; exec_error = true;
debug(1, L"waitpid(%d) call in unblock_pid failed:!\n", p->pid); debug(1, L"waitpid(%d) call in unblock_pid failed:!\n", p->pid);
wperror(L"waitpid"); wperror(L"waitpid");

View File

@ -819,33 +819,22 @@ bool terminal_give_to_job(job_t *j, int cont) {
//thing is that we can guarantee the process isn't going to exit while we wait (which would cause us to //thing is that we can guarantee the process isn't going to exit while we wait (which would cause us to
//possibly block indefinitely). //possibly block indefinitely).
auto pgroupTerminated = [&j]() {
//everyone in the process group has exited
//The only way that can happen is if the very last process in the group terminated, and didn't need
//to access the terminal, otherwise it would have hung waiting for terminal IO. We can ignore this.
debug(3, L"terminal_give_to_job(): tcsetpgrp called but process group %d has terminated.\n", j->pgid);
};
while (tcsetpgrp(STDIN_FILENO, j->pgid) != 0) { while (tcsetpgrp(STDIN_FILENO, j->pgid) != 0) {
if (errno == EINTR) { if (errno == EINTR) {
//always retry on EINTR //always retry on EINTR
} }
else if (errno == EINVAL) {
//OS X returns EINVAL if the process group no longer lives. Probably other OSes, too.
//See comments in pgroupTerminated() above.
pgroupTerminated();
break;
}
else if (errno == EPERM) { else if (errno == EPERM) {
//retry so long as this isn't because the process group is dead //so long as this isn't because the process group is dead
int wait_result = waitpid(-1 * j->pgid, &wait_result, WNOHANG); int wait_result = waitpid(-1 * j->pgid, &wait_result, WNOHANG);
if (wait_result == -1) { if (wait_result == -1) {
//everyone in the process group has exited
//The only way that can happen is if the very last process in the group terminated, and didn't need
//to access the terminal, otherwise it would have hung waiting for terminal IO. We can ignore this.
//Note that -1 is technically an "error" for waitpid in the sense that an invalid argument was specified //Note that -1 is technically an "error" for waitpid in the sense that an invalid argument was specified
//because no such process group exists any longer. This is the observed behavior on Linux 4.4.0. //because no such process group exists any longer.
//a "success" result would mean processes from the group still exist but is still running in some state //a "success" result would mean processes from the group still exist but is still running in some state
//or the other. //or the other.
//See comments in pgroupTerminated() above. debug(3, L"terminal_give_to_job(): tcsetpgrp called but process group %d has terminated.\n", j->pgid);
pgroupTerminated();
break; break;
} }
debug(2, L"terminal_give_to_job(): EPERM.\n", j->pgid); debug(2, L"terminal_give_to_job(): EPERM.\n", j->pgid);