diff --git a/src/postfork.cpp b/src/postfork.cpp index 2751411d2..93281b28a 100644 --- a/src/postfork.cpp +++ b/src/postfork.cpp @@ -106,15 +106,25 @@ bool child_set_group(job_t *j, process_t *p) { /// if it's to run in the foreground. bool set_child_group(job_t *j, pid_t child_pid) { if (j->get_flag(JOB_CONTROL)) { - assert (j->pgid != -2 && "set_child_group called with JOB_CONTROL before job pgid determined!"); + assert (j->pgid != -2 + && "set_child_group called with JOB_CONTROL before job pgid determined!"); // The parent sets the child's group. This incurs the well-known unavoidable race with the // child exiting, so ignore ESRCH and EPERM (in case the pid was recycled). + // Additionally ignoring EACCES. See #4715 and #4884. if (setpgid(child_pid, j->pgid) < 0) { - if (errno != ESRCH && errno != EPERM) { + if (errno != ESRCH && errno != EPERM && errno != EACCES) { safe_perror("setpgid"); return false; } + else { + // Just in case it's ever not right to ignore the setpgid call, (i.e. if this + // ever leads to a terminal hang due if both this setpgid call AND posix_spawn's + // internal setpgid calls failed), write to the debug log so a future developer + // doesn't go crazy trying to track this down. + debug(2, "Error %d while calling setpgid for child %d (probably harmless)", + errno, child_pid); + } } } else { j->pgid = getpgrp();