Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

tools subcmd: Add non-waitpid check_if_command_finished()

Using waitpid can cause stdout/stderr of the child process to be
lost. Use Linux's /prod/<pid>/status file to determine if the process
has reached the zombie state. Use the 'status' file rather than 'stat'
to avoid issues around skipping the process name.

Tested-by: James Clark <james.clark@linaro.org>
Signed-off-by: Ian Rogers <irogers@google.com>
Cc: Colin Ian King <colin.i.king@gmail.com>
Cc: Howard Chu <howardchu95@gmail.com>
Cc: Weilin Wang <weilin.wang@intel.com>
Cc: Ilya Leoshkevich <iii@linux.ibm.com>
Cc: Thomas Richter <tmricht@linux.ibm.com>
Cc: Andi Kleen <ak@linux.intel.com>
Cc: Dapeng Mi <dapeng1.mi@linux.intel.com>
Cc: Athira Jajeev <atrajeev@linux.vnet.ibm.com>
Cc: Michael Petlan <mpetlan@redhat.com>
Cc: Veronika Molnarova <vmolnaro@redhat.com>
Link: https://lore.kernel.org/r/20241025192109.132482-2-irogers@google.com
Signed-off-by: Namhyung Kim <namhyung@kernel.org>

authored by

Ian Rogers and committed by
Namhyung Kim
5ce42b5d 150dab31

+33
+33
tools/lib/subcmd/run-command.c
··· 2 2 #include <unistd.h> 3 3 #include <sys/types.h> 4 4 #include <sys/stat.h> 5 + #include <ctype.h> 5 6 #include <fcntl.h> 6 7 #include <string.h> 7 8 #include <linux/string.h> ··· 218 217 219 218 int check_if_command_finished(struct child_process *cmd) 220 219 { 220 + #ifdef __linux__ 221 + char filename[FILENAME_MAX + 12]; 222 + char status_line[256]; 223 + FILE *status_file; 224 + 225 + /* 226 + * Check by reading /proc/<pid>/status as calling waitpid causes 227 + * stdout/stderr to be closed and data lost. 228 + */ 229 + sprintf(filename, "/proc/%d/status", cmd->pid); 230 + status_file = fopen(filename, "r"); 231 + if (status_file == NULL) { 232 + /* Open failed assume finish_command was called. */ 233 + return true; 234 + } 235 + while (fgets(status_line, sizeof(status_line), status_file) != NULL) { 236 + char *p; 237 + 238 + if (strncmp(status_line, "State:", 6)) 239 + continue; 240 + 241 + fclose(status_file); 242 + p = status_line + 6; 243 + while (isspace(*p)) 244 + p++; 245 + return *p == 'Z' ? 1 : 0; 246 + } 247 + /* Read failed assume finish_command was called. */ 248 + fclose(status_file); 249 + return 1; 250 + #else 221 251 wait_or_whine(cmd, /*block=*/false); 222 252 return cmd->finished; 253 + #endif 223 254 } 224 255 225 256 int finish_command(struct child_process *cmd)