mirror of
https://github.com/torvalds/linux.git
synced 2024-11-22 12:11:40 +00:00
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>
This commit is contained in:
parent
8c004c7a60
commit
705c09bb3c
@ -165,43 +165,65 @@ int start_command(struct child_process *cmd)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int wait_or_whine(pid_t pid)
|
||||
static int wait_or_whine(struct child_process *cmd, bool block)
|
||||
{
|
||||
char sbuf[STRERR_BUFSIZE];
|
||||
bool finished = cmd->finished;
|
||||
int result = cmd->finish_result;
|
||||
|
||||
for (;;) {
|
||||
while (!finished) {
|
||||
int status, code;
|
||||
pid_t waiting = waitpid(pid, &status, 0);
|
||||
pid_t waiting = waitpid(cmd->pid, &status, block ? 0 : WNOHANG);
|
||||
|
||||
if (!block && waiting == 0)
|
||||
break;
|
||||
|
||||
if (waiting < 0 && errno == EINTR)
|
||||
continue;
|
||||
|
||||
finished = true;
|
||||
if (waiting < 0) {
|
||||
if (errno == EINTR)
|
||||
continue;
|
||||
char sbuf[STRERR_BUFSIZE];
|
||||
|
||||
fprintf(stderr, " Error: waitpid failed (%s)",
|
||||
str_error_r(errno, sbuf, sizeof(sbuf)));
|
||||
return -ERR_RUN_COMMAND_WAITPID;
|
||||
}
|
||||
if (waiting != pid)
|
||||
return -ERR_RUN_COMMAND_WAITPID_WRONG_PID;
|
||||
if (WIFSIGNALED(status))
|
||||
return -ERR_RUN_COMMAND_WAITPID_SIGNAL;
|
||||
|
||||
if (!WIFEXITED(status))
|
||||
return -ERR_RUN_COMMAND_WAITPID_NOEXIT;
|
||||
code = WEXITSTATUS(status);
|
||||
switch (code) {
|
||||
case 127:
|
||||
return -ERR_RUN_COMMAND_EXEC;
|
||||
case 0:
|
||||
return 0;
|
||||
default:
|
||||
return -code;
|
||||
result = -ERR_RUN_COMMAND_WAITPID;
|
||||
} else if (waiting != cmd->pid) {
|
||||
result = -ERR_RUN_COMMAND_WAITPID_WRONG_PID;
|
||||
} else 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (finished) {
|
||||
cmd->finished = 1;
|
||||
cmd->finish_result = result;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
int check_if_command_finished(struct child_process *cmd)
|
||||
{
|
||||
wait_or_whine(cmd, /*block=*/false);
|
||||
return cmd->finished;
|
||||
}
|
||||
|
||||
int finish_command(struct child_process *cmd)
|
||||
{
|
||||
return wait_or_whine(cmd->pid);
|
||||
return wait_or_whine(cmd, /*block=*/true);
|
||||
}
|
||||
|
||||
int run_command(struct child_process *cmd)
|
||||
|
@ -41,17 +41,20 @@ struct child_process {
|
||||
int err;
|
||||
const char *dir;
|
||||
const char *const *env;
|
||||
int finish_result;
|
||||
unsigned no_stdin:1;
|
||||
unsigned no_stdout:1;
|
||||
unsigned no_stderr:1;
|
||||
unsigned exec_cmd:1; /* if this is to be external sub-command */
|
||||
unsigned stdout_to_stderr:1;
|
||||
unsigned finished:1;
|
||||
void (*preexec_cb)(void);
|
||||
/* If set, call function in child rather than doing an exec. */
|
||||
int (*no_exec_cmd)(struct child_process *process);
|
||||
};
|
||||
|
||||
int start_command(struct child_process *);
|
||||
int check_if_command_finished(struct child_process *);
|
||||
int finish_command(struct child_process *);
|
||||
int run_command(struct child_process *);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user