summaryrefslogtreecommitdiff
path: root/run-command.c
diff options
context:
space:
mode:
authorJunio C Hamano <gitster@pobox.com>2007-11-01 13:47:47 -0700
committerJunio C Hamano <gitster@pobox.com>2007-11-01 13:47:47 -0700
commit4340a813d007b592534de664d152d66417dbe809 (patch)
tree731be77f39c37cd0c6b1ddf5bf8e50f1692ae9e7 /run-command.c
parent6959893b0b65ebc68ce2fb524a8ec15a26ca4972 (diff)
parent546bb5823249678bc6ad11e65661d896ed83448a (diff)
downloadgit-4340a813d007b592534de664d152d66417dbe809.tar.gz
Merge branch 'js/forkexec'
* js/forkexec: Use the asyncronous function infrastructure to run the content filter. Avoid a dup2(2) in apply_filter() - start_command() can do it for us. t0021-conversion.sh: Test that the clean filter really cleans content. upload-pack: Run rev-list in an asynchronous function. upload-pack: Move the revision walker into a separate function. Use the asyncronous function infrastructure in builtin-fetch-pack.c. Add infrastructure to run a function asynchronously. upload-pack: Use start_command() to run pack-objects in create_pack_file(). Have start_command() create a pipe to read the stderr of the child. Use start_comand() in builtin-fetch-pack.c instead of explicit fork/exec. Use run_command() to spawn external diff programs instead of fork/exec. Use start_command() to run content filters instead of explicit fork/exec. Use start_command() in git_connect() instead of explicit fork/exec. Change git_connect() to return a struct child_process instead of a pid_t. Conflicts: builtin-fetch-pack.c
Diffstat (limited to 'run-command.c')
-rw-r--r--run-command.c77
1 files changed, 67 insertions, 10 deletions
diff --git a/run-command.c b/run-command.c
index 7e779d33ee..d99a6c4ea7 100644
--- a/run-command.c
+++ b/run-command.c
@@ -17,8 +17,8 @@ static inline void dup_devnull(int to)
int start_command(struct child_process *cmd)
{
- int need_in, need_out;
- int fdin[2], fdout[2];
+ int need_in, need_out, need_err;
+ int fdin[2], fdout[2], fderr[2];
need_in = !cmd->no_stdin && cmd->in < 0;
if (need_in) {
@@ -41,12 +41,26 @@ int start_command(struct child_process *cmd)
cmd->close_out = 1;
}
+ need_err = cmd->err < 0;
+ if (need_err) {
+ if (pipe(fderr) < 0) {
+ if (need_in)
+ close_pair(fdin);
+ if (need_out)
+ close_pair(fdout);
+ return -ERR_RUN_COMMAND_PIPE;
+ }
+ cmd->err = fderr[0];
+ }
+
cmd->pid = fork();
if (cmd->pid < 0) {
if (need_in)
close_pair(fdin);
if (need_out)
close_pair(fdout);
+ if (need_err)
+ close_pair(fderr);
return -ERR_RUN_COMMAND_FORK;
}
@@ -73,6 +87,11 @@ int start_command(struct child_process *cmd)
close(cmd->out);
}
+ if (need_err) {
+ dup2(fderr[1], 2);
+ close_pair(fderr);
+ }
+
if (cmd->dir && chdir(cmd->dir))
die("exec %s: cd to %s failed (%s)", cmd->argv[0],
cmd->dir, strerror(errno));
@@ -102,19 +121,17 @@ int start_command(struct child_process *cmd)
else if (cmd->out > 1)
close(cmd->out);
+ if (need_err)
+ close(fderr[1]);
+
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)
@@ -122,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;
@@ -136,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);
@@ -178,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;
+}