And persistent_waitpid() to recover the information from the last run. Signed-off-by: Felipe Contreras <felipe.contreras@xxxxxxxxx> --- run-command.c | 46 ++++++++++++++++++++++++++++++++++++++++------ run-command.h | 6 ++++++ 2 files changed, 46 insertions(+), 6 deletions(-) diff --git a/run-command.c b/run-command.c index 07e27ff..16833df 100644 --- a/run-command.c +++ b/run-command.c @@ -226,14 +226,27 @@ static inline void set_cloexec(int fd) fcntl(fd, F_SETFD, flags | FD_CLOEXEC); } -static int wait_or_whine(pid_t pid, const char *argv0) +static pid_t persistent_waitpid(struct child_process *cmd, pid_t pid, int *stat_loc) +{ + if (cmd->last_wait.code) { + errno = cmd->last_wait.failed_errno; + *stat_loc = cmd->last_wait.status; + return errno ? -1 : pid; + } else { + pid_t waiting; + while ((waiting = waitpid(pid, stat_loc, 0)) < 0 && errno == EINTR) + ; /* nothing */ + return waiting; + } +} + +static int wait_or_whine(struct child_process *cmd, pid_t pid, const char *argv0) { int status, code = -1; pid_t waiting; int failed_errno = 0; - while ((waiting = waitpid(pid, &status, 0)) < 0 && errno == EINTR) - ; /* nothing */ + waiting = persistent_waitpid(cmd, pid, &status); if (waiting < 0) { failed_errno = errno; @@ -437,7 +450,7 @@ fail_pipe: * At this point we know that fork() succeeded, but execvp() * failed. Errors have been reported to our stderr. */ - wait_or_whine(cmd->pid, cmd->argv[0]); + wait_or_whine(cmd, cmd->pid, cmd->argv[0]); failed_errno = errno; cmd->pid = -1; } @@ -542,7 +555,7 @@ fail_pipe: int finish_command(struct child_process *cmd) { - return wait_or_whine(cmd->pid, cmd->argv[0]); + return wait_or_whine(cmd, cmd->pid, cmd->argv[0]); } int run_command(struct child_process *cmd) @@ -553,6 +566,27 @@ int run_command(struct child_process *cmd) return finish_command(cmd); } +int check_command(struct child_process *cmd) +{ + int status; + pid_t waiting; + int failed_errno = 0; + + waiting = waitpid(cmd->pid, &status, WNOHANG); + + if (waiting != cmd->pid) + return 1; + + if (waiting < 0) + failed_errno = errno; + + cmd->last_wait.code = -1; + cmd->last_wait.failed_errno = failed_errno; + cmd->last_wait.status = status; + + return 0; +} + static void prepare_run_command_v_opt(struct child_process *cmd, const char **argv, int opt) @@ -729,7 +763,7 @@ error: int finish_async(struct async *async) { #ifdef NO_PTHREADS - return wait_or_whine(async->pid, "child process"); + return wait_or_whine(cmd, async->pid, "child process"); #else void *ret = (void *)(intptr_t)(-1); diff --git a/run-command.h b/run-command.h index 221ce33..66aaac7 100644 --- a/run-command.h +++ b/run-command.h @@ -39,11 +39,17 @@ struct child_process { unsigned stdout_to_stderr:1; unsigned use_shell:1; unsigned clean_on_exit:1; + struct last_wait { + int code; + int failed_errno; + int status; + } last_wait; }; int start_command(struct child_process *); int finish_command(struct child_process *); int run_command(struct child_process *); +int check_command(struct child_process *); extern char *find_hook(const char *name); extern int run_hook(const char *index_file, const char *name, ...); -- 1.8.2 -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html