diff --git a/src/exec.cpp b/src/exec.cpp index bb50371f2..34ffa0dca 100644 --- a/src/exec.cpp +++ b/src/exec.cpp @@ -1083,22 +1083,27 @@ void exec_job(parser_t &parser, job_t *j) { child_spawned = true; on_process_created(j, p->pid); - //We explicitly don't call set_child_group() for spawned processes because that - //a) isn't necessary, and b) causes issues like fish-shell/fish-shell#4715 + // We explicitly don't call set_child_group() for spawned processes because that + // a) isn't necessary, and b) causes issues like fish-shell/fish-shell#4715 - //However, on WSL `posix_spawn` does not correctly set the pgroup for the child process - //See fish-shell/fish-shell#4778, blocked by Microsoft/WSL#2997 - if (is_windows_subsystem_for_linux()) { +#if defined(__GLIBC__) + // Unfortunately, using posix_spawn() is not the panacea it would appear to be, glibc has + // a penchant for using fork() instead of vfork() when posix_spawn() is called, meaning that + // atomicity is not guaranteed and we can get here before the child group has been set. + // See discussion here: https://github.com/Microsoft/WSL/issues/2997 + // And confirmation that this persists past glibc 2.24+ here: + // https://github.com/fish-shell/fish-shell/issues/4715 + if (j->get_flag(JOB_CONTROL) && getpgid(p->pid) != j->pgid) { set_child_group(j, p->pid); } - else { - //in do_fork, the pid of the child process is used as the group leader if j->pgid == 2 - //above, posix_spawn assigned the new group a pgid equal to its own id if j->pgid == 2 - //so this is what we do instead of calling set_child_group: - if (j->pgid == -2) { - j->pgid = pid; - } +#else + // In do_fork, the pid of the child process is used as the group leader if j->pgid == 2 + // above, posix_spawn assigned the new group a pgid equal to its own id if j->pgid == 2 + // so this is what we do instead of calling set_child_group: + if (j->pgid == -2) { + j->pgid = pid; } +#endif maybe_assign_terminal(j); } else