Add infrastructure to run a function asynchronously.
[git/git.git] / run-command.c
index d00c03b..d99a6c4 100644 (file)
@@ -127,16 +127,11 @@ int start_command(struct child_process *cmd)
        return 0;
 }
 
-int finish_command(struct child_process *cmd)
+static int wait_or_whine(pid_t pid)
 {
-       if (cmd->close_in)
-               close(cmd->in);
-       if (cmd->close_out)
-               close(cmd->out);
-
        for (;;) {
                int status, code;
-               pid_t waiting = waitpid(cmd->pid, &status, 0);
+               pid_t waiting = waitpid(pid, &status, 0);
 
                if (waiting < 0) {
                        if (errno == EINTR)
@@ -144,7 +139,7 @@ int finish_command(struct child_process *cmd)
                        error("waitpid failed (%s)", strerror(errno));
                        return -ERR_RUN_COMMAND_WAITPID;
                }
-               if (waiting != cmd->pid)
+               if (waiting != pid)
                        return -ERR_RUN_COMMAND_WAITPID_WRONG_PID;
                if (WIFSIGNALED(status))
                        return -ERR_RUN_COMMAND_WAITPID_SIGNAL;
@@ -158,6 +153,15 @@ int finish_command(struct child_process *cmd)
        }
 }
 
+int finish_command(struct child_process *cmd)
+{
+       if (cmd->close_in)
+               close(cmd->in);
+       if (cmd->close_out)
+               close(cmd->out);
+       return wait_or_whine(cmd->pid);
+}
+
 int run_command(struct child_process *cmd)
 {
        int code = start_command(cmd);
@@ -200,3 +204,34 @@ int run_command_v_opt_cd_env(const char **argv, int opt, const char *dir, const
        cmd.env = env;
        return run_command(&cmd);
 }
+
+int start_async(struct async *async)
+{
+       int pipe_out[2];
+
+       if (pipe(pipe_out) < 0)
+               return error("cannot create pipe: %s", strerror(errno));
+
+       async->pid = fork();
+       if (async->pid < 0) {
+               error("fork (async) failed: %s", strerror(errno));
+               close_pair(pipe_out);
+               return -1;
+       }
+       if (!async->pid) {
+               close(pipe_out[0]);
+               exit(!!async->proc(pipe_out[1], async->data));
+       }
+       async->out = pipe_out[0];
+       close(pipe_out[1]);
+       return 0;
+}
+
+int finish_async(struct async *async)
+{
+       int ret = 0;
+
+       if (wait_or_whine(async->pid))
+               ret = error("waitpid (async) failed");
+       return ret;
+}