diff options
author | Johannes Sixt <johannes.sixt@telecom.at> | 2007-10-19 21:48:00 +0200 |
---|---|---|
committer | Shawn O. Pearce <spearce@spearce.org> | 2007-10-21 01:30:41 -0400 |
commit | 2d22c208304156892fd6674e0055a3212c1e2d2e (patch) | |
tree | 48102e69b4db1fbd0b1513df225e05fd06bb1612 /run-command.c | |
parent | cc41fa8da9b9e9d23221d3be47a80409a89732d4 (diff) | |
download | git-2d22c208304156892fd6674e0055a3212c1e2d2e.tar.gz |
Add infrastructure to run a function asynchronously.
This adds start_async() and finish_async(), which runs a function
asynchronously. Communication with the caller happens only via pipes.
For this reason, this implementation forks off a child process that runs
the function.
[sp: Style nit fixed by removing unnecessary block on if condition
inside of start_async()]
Signed-off-by: Johannes Sixt <johannes.sixt@telecom.at>
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
Diffstat (limited to 'run-command.c')
-rw-r--r-- | run-command.c | 51 |
1 files changed, 43 insertions, 8 deletions
diff --git a/run-command.c b/run-command.c index d00c03bbdf..d99a6c4ea7 100644 --- a/run-command.c +++ b/run-command.c @@ -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; +} |