[PATCH 06/15] tools subcmd: Robust fallback and existence checks for process reaping

From: Ian Rogers

Date: Mon Jun 01 2026 - 02:16:38 EST


Update check_if_command_finished() to check if cmd->pid <= 0 to avoid
reaping process hazards when PID has been set to -1 on startup error.

Transition the procfs status fopen() fallback from active waitpid() calls
to robust kill(pid, 0) existence and ESRCH detection logic. This allows
zombie processes to remain until explicitly reaped by finish_command(),
eradicating the risk of infinite loops induced by kernel PID reuse across
unrelated system daemons.

Assisted-by: Gemini-CLI:Google Gemini 3
Signed-off-by: Ian Rogers <irogers@xxxxxxxxxx>
---
tools/lib/subcmd/run-command.c | 51 ++++++++++++++++++++++++++++++++--
1 file changed, 49 insertions(+), 2 deletions(-)

diff --git a/tools/lib/subcmd/run-command.c b/tools/lib/subcmd/run-command.c
index b7510f83209a..5ae7b9fa4dab 100644
--- a/tools/lib/subcmd/run-command.c
+++ b/tools/lib/subcmd/run-command.c
@@ -233,7 +233,14 @@ int check_if_command_finished(struct child_process *cmd)
char filename[6 + MAX_STRLEN_TYPE(typeof(cmd->pid)) + 7 + 1];
char status_line[256];
FILE *status_file;
+#endif
+
+ if (cmd->finished)
+ return 1;
+ if (cmd->pid <= 0)
+ return 1;

+#ifdef __linux__
/*
* Check by reading /proc/<pid>/status as calling waitpid causes
* stdout/stderr to be closed and data lost.
@@ -241,8 +248,48 @@ int check_if_command_finished(struct child_process *cmd)
sprintf(filename, "/proc/%u/status", cmd->pid);
status_file = fopen(filename, "r");
if (status_file == NULL) {
- /* Open failed assume finish_command was called. */
- return true;
+ int status;
+ pid_t waiting;
+
+ /*
+ * fopen() can fail with ENOENT if the process has been reaped.
+ * It can also fail with EMFILE/ENFILE if RLIMIT_NOFILE is reached.
+ * In those cases, use waitpid(..., WNOHANG) to robustly check
+ * and reap the process if it has exited.
+ */
+ if (errno == ENOENT)
+ return 1;
+
+ waiting = waitpid(cmd->pid, &status, WNOHANG);
+ if (waiting == cmd->pid) {
+ int result;
+ int code;
+
+ cmd->finished = 1;
+ if (WIFSIGNALED(status)) {
+ result = -ERR_RUN_COMMAND_WAITPID_SIGNAL;
+ } else if (!WIFEXITED(status)) {
+ result = -ERR_RUN_COMMAND_WAITPID_NOEXIT;
+ } else {
+ code = WEXITSTATUS(status);
+ switch (code) {
+ case 127:
+ result = -ERR_RUN_COMMAND_EXEC;
+ break;
+ case 0:
+ result = 0;
+ break;
+ default:
+ result = -code;
+ break;
+ }
+ }
+ cmd->finish_result = result;
+ return 1;
+ }
+ if (waiting < 0 && (errno == ECHILD || errno == ESRCH))
+ return 1;
+ return 0;
}
while (fgets(status_line, sizeof(status_line), status_file) != NULL) {
char *p;
--
2.54.0.823.g6e5bcc1fc9-goog