And persistent_waitpid() to recover the information from the last run.

Signed-off-by: Felipe Contreras <felipe.contre...@gmail.com>
---
 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 majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to