Skip to content

Commit 5ce42b5

Browse files
captain5050namhyung
authored andcommitted
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 <[email protected]> Signed-off-by: Ian Rogers <[email protected]> Cc: Colin Ian King <[email protected]> Cc: Howard Chu <[email protected]> Cc: Weilin Wang <[email protected]> Cc: Ilya Leoshkevich <[email protected]> Cc: Thomas Richter <[email protected]> Cc: Andi Kleen <[email protected]> Cc: Dapeng Mi <[email protected]> Cc: Athira Jajeev <[email protected]> Cc: Michael Petlan <[email protected]> Cc: Veronika Molnarova <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Namhyung Kim <[email protected]>
1 parent 150dab3 commit 5ce42b5

File tree

1 file changed

+33
-0
lines changed

1 file changed

+33
-0
lines changed

tools/lib/subcmd/run-command.c

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
#include <unistd.h>
33
#include <sys/types.h>
44
#include <sys/stat.h>
5+
#include <ctype.h>
56
#include <fcntl.h>
67
#include <string.h>
78
#include <linux/string.h>
@@ -217,8 +218,40 @@ static int wait_or_whine(struct child_process *cmd, bool block)
217218

218219
int check_if_command_finished(struct child_process *cmd)
219220
{
221+
#ifdef __linux__
222+
char filename[FILENAME_MAX + 12];
223+
char status_line[256];
224+
FILE *status_file;
225+
226+
/*
227+
* Check by reading /proc/<pid>/status as calling waitpid causes
228+
* stdout/stderr to be closed and data lost.
229+
*/
230+
sprintf(filename, "/proc/%d/status", cmd->pid);
231+
status_file = fopen(filename, "r");
232+
if (status_file == NULL) {
233+
/* Open failed assume finish_command was called. */
234+
return true;
235+
}
236+
while (fgets(status_line, sizeof(status_line), status_file) != NULL) {
237+
char *p;
238+
239+
if (strncmp(status_line, "State:", 6))
240+
continue;
241+
242+
fclose(status_file);
243+
p = status_line + 6;
244+
while (isspace(*p))
245+
p++;
246+
return *p == 'Z' ? 1 : 0;
247+
}
248+
/* Read failed assume finish_command was called. */
249+
fclose(status_file);
250+
return 1;
251+
#else
220252
wait_or_whine(cmd, /*block=*/false);
221253
return cmd->finished;
254+
#endif
222255
}
223256

224257
int finish_command(struct child_process *cmd)

0 commit comments

Comments
 (0)