And to recover the information from the last run when running
wait_or_whine().

Signed-off-by: Felipe Contreras <felipe.contre...@gmail.com>
---
 run-command.c | 46 ++++++++++++++++++++++++++++++++++++++++------
 run-command.h |  5 +++++
 2 files changed, 45 insertions(+), 6 deletions(-)

diff --git a/run-command.c b/run-command.c
index 07e27ff..5cb5114 100644
--- a/run-command.c
+++ b/run-command.c
@@ -226,14 +226,20 @@ 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 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 */
+       /* First try the last status from check_command() */
+       if (cmd && cmd->last_status.valid) {
+               status = cmd->last_status.status;
+               waiting = pid;
+       } else {
+               while ((waiting = waitpid(pid, status, 0)) < 0 && errno == 
EINTR)
+                       ;       /* nothing */
+       }
 
        if (waiting < 0) {
                failed_errno = errno;
@@ -276,6 +282,8 @@ int start_command(struct child_process *cmd)
        int failed_errno = failed_errno;
        char *str;
 
+       cmd->last_status.valid = 0;
+
        /*
         * In case of errors we must keep the promise to close FDs
         * that have been passed in via ->in and ->out.
@@ -437,7 +445,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 +550,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 +561,32 @@ int run_command(struct child_process *cmd)
        return finish_command(cmd);
 }
 
+int check_command(struct child_process *cmd)
+{
+       int status;
+       pid_t waiting;
+
+       if (cmd->last_status.valid)
+               return 0;
+
+       while ((waiting = waitpid(cmd->pid, &status, WNOHANG)) < 0 && errno == 
EINTR)
+               ; /* nothing */
+
+       if (!waiting)
+               return 1;
+
+       if (waiting == cmd->pid) {
+               cmd->last_status.valid = 1;
+               cmd->last_status.status = status;
+               return 0;
+       }
+
+       if (waiting > 0)
+               die("BUG: waitpid reported a random pid?");
+
+       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(NULL, async->pid, "child process");
 #else
        void *ret = (void *)(intptr_t)(-1);
 
diff --git a/run-command.h b/run-command.h
index 221ce33..74a733d 100644
--- a/run-command.h
+++ b/run-command.h
@@ -39,11 +39,16 @@ struct child_process {
        unsigned stdout_to_stderr:1;
        unsigned use_shell:1;
        unsigned clean_on_exit:1;
+       struct last_status {
+               unsigned valid:1;
+               int status;
+       } last_status;
 };
 
 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