diff -u a/Src/exec.c b/Src/exec.c --- a/Src/exec.c 2022-05-08 01:18:22.000000000 -0500 +++ b/Src/exec.c 2026-02-25 22:23:44.602848997 -0600 @@ -4679,7 +4679,34 @@ zclose(pipes[1]); retval = readoutput(pipes[0], qt, NULL); fdtable[pipes[0]] = FDT_UNUSED; - waitforpid(pid, 0); /* unblocks */ + wait_for_processes(); + /* + * The SIGCHLD handler may already have reaped the command + * substitution child while readoutput() had signals unblocked. + * In that case cmdoutpid is cleared, and calling waitforpid() + * on a stale PID can hang if the PID has been reused. + */ + if (cmdoutpid == pid) { + int status; + pid_t waitret; + + while ((waitret = waitpid(pid, &status, 0)) < 0 && errno == EINTR) + ; + if (waitret == pid) { + cmdoutpid = 0; + if (WIFSIGNALED(status)) + cmdoutval = (0200 | WTERMSIG(status)); + else + cmdoutval = WEXITSTATUS(status); + use_cmdoutval = 1; + get_usage(); + } else if (waitret < 0 && errno == ECHILD) { + wait_for_processes(); + if (cmdoutpid == pid) + cmdoutpid = 0; + } + } + child_unblock(); lastval = cmdoutval; return retval; } @@ -4884,7 +4911,22 @@ return nam; } else if (pid) { close(fd); - waitforpid(pid, 0); + wait_for_processes(); + if (cmdoutpid == pid) { + int status; + pid_t waitret; + + while ((waitret = waitpid(pid, &status, 0)) < 0 && errno == EINTR) + ; + if (waitret == pid) + cmdoutpid = 0; + else if (waitret < 0 && errno == ECHILD) { + wait_for_processes(); + if (cmdoutpid == pid) + cmdoutpid = 0; + } + } + child_unblock(); cmdoutval = 0; return nam; }