64 lines
1.6 KiB
Diff
64 lines
1.6 KiB
Diff
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;
|
|
}
|