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

tools subcmd: Add check_if_command_finished()

Add non-blocking function to check if a 'struct child_process' has
completed. If the process has completed the exit code is stored in the
'struct child_process' so that finish_command() returns it.

Signed-off-by: Ian Rogers <irogers@google.com>
Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: James Clark <james.clark@arm.com>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Kan Liang <kan.liang@linux.intel.com>
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Link: https://lore.kernel.org/r/20240405070931.1231245-1-irogers@google.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>

authored by

Ian Rogers and committed by
Arnaldo Carvalho de Melo
705c09bb 8c004c7a

+49 -24
+46 -24
tools/lib/subcmd/run-command.c
··· 165 165 return 0; 166 166 } 167 167 168 - static int wait_or_whine(pid_t pid) 168 + static int wait_or_whine(struct child_process *cmd, bool block) 169 169 { 170 - char sbuf[STRERR_BUFSIZE]; 170 + bool finished = cmd->finished; 171 + int result = cmd->finish_result; 171 172 172 - for (;;) { 173 + while (!finished) { 173 174 int status, code; 174 - pid_t waiting = waitpid(pid, &status, 0); 175 + pid_t waiting = waitpid(cmd->pid, &status, block ? 0 : WNOHANG); 175 176 177 + if (!block && waiting == 0) 178 + break; 179 + 180 + if (waiting < 0 && errno == EINTR) 181 + continue; 182 + 183 + finished = true; 176 184 if (waiting < 0) { 177 - if (errno == EINTR) 178 - continue; 185 + char sbuf[STRERR_BUFSIZE]; 186 + 179 187 fprintf(stderr, " Error: waitpid failed (%s)", 180 188 str_error_r(errno, sbuf, sizeof(sbuf))); 181 - return -ERR_RUN_COMMAND_WAITPID; 182 - } 183 - if (waiting != pid) 184 - return -ERR_RUN_COMMAND_WAITPID_WRONG_PID; 185 - if (WIFSIGNALED(status)) 186 - return -ERR_RUN_COMMAND_WAITPID_SIGNAL; 187 - 188 - if (!WIFEXITED(status)) 189 - return -ERR_RUN_COMMAND_WAITPID_NOEXIT; 190 - code = WEXITSTATUS(status); 191 - switch (code) { 192 - case 127: 193 - return -ERR_RUN_COMMAND_EXEC; 194 - case 0: 195 - return 0; 196 - default: 197 - return -code; 189 + result = -ERR_RUN_COMMAND_WAITPID; 190 + } else if (waiting != cmd->pid) { 191 + result = -ERR_RUN_COMMAND_WAITPID_WRONG_PID; 192 + } else if (WIFSIGNALED(status)) { 193 + result = -ERR_RUN_COMMAND_WAITPID_SIGNAL; 194 + } else if (!WIFEXITED(status)) { 195 + result = -ERR_RUN_COMMAND_WAITPID_NOEXIT; 196 + } else { 197 + code = WEXITSTATUS(status); 198 + switch (code) { 199 + case 127: 200 + result = -ERR_RUN_COMMAND_EXEC; 201 + break; 202 + case 0: 203 + result = 0; 204 + break; 205 + default: 206 + result = -code; 207 + break; 208 + } 198 209 } 199 210 } 211 + if (finished) { 212 + cmd->finished = 1; 213 + cmd->finish_result = result; 214 + } 215 + return result; 216 + } 217 + 218 + int check_if_command_finished(struct child_process *cmd) 219 + { 220 + wait_or_whine(cmd, /*block=*/false); 221 + return cmd->finished; 200 222 } 201 223 202 224 int finish_command(struct child_process *cmd) 203 225 { 204 - return wait_or_whine(cmd->pid); 226 + return wait_or_whine(cmd, /*block=*/true); 205 227 } 206 228 207 229 int run_command(struct child_process *cmd)
+3
tools/lib/subcmd/run-command.h
··· 41 41 int err; 42 42 const char *dir; 43 43 const char *const *env; 44 + int finish_result; 44 45 unsigned no_stdin:1; 45 46 unsigned no_stdout:1; 46 47 unsigned no_stderr:1; 47 48 unsigned exec_cmd:1; /* if this is to be external sub-command */ 48 49 unsigned stdout_to_stderr:1; 50 + unsigned finished:1; 49 51 void (*preexec_cb)(void); 50 52 /* If set, call function in child rather than doing an exec. */ 51 53 int (*no_exec_cmd)(struct child_process *process); 52 54 }; 53 55 54 56 int start_command(struct child_process *); 57 + int check_if_command_finished(struct child_process *); 55 58 int finish_command(struct child_process *); 56 59 int run_command(struct child_process *); 57 60