summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--builtin-send-pack.c14
-rw-r--r--builtin-verify-tag.c1
-rw-r--r--bundle.c5
-rw-r--r--run-command.c22
-rw-r--r--run-command.h18
5 files changed, 49 insertions, 11 deletions
diff --git a/builtin-send-pack.c b/builtin-send-pack.c
index ba9bc91a5c..b0cfae83fc 100644
--- a/builtin-send-pack.c
+++ b/builtin-send-pack.c
@@ -404,12 +404,15 @@ static int do_send_pack(int in, int out, struct remote *remote, const char *dest
if (!remote_tail)
remote_tail = &remote_refs;
if (match_refs(local_refs, remote_refs, &remote_tail,
- nr_refspec, refspec, flags))
+ nr_refspec, refspec, flags)) {
+ close(out);
return -1;
+ }
if (!remote_refs) {
fprintf(stderr, "No refs in common and none specified; doing nothing.\n"
"Perhaps you should specify a branch such as 'master'.\n");
+ close(out);
return 0;
}
@@ -496,12 +499,11 @@ static int do_send_pack(int in, int out, struct remote *remote, const char *dest
packet_flush(out);
if (new_refs && !args.dry_run) {
- if (pack_objects(out, remote_refs) < 0) {
- close(out);
+ if (pack_objects(out, remote_refs) < 0)
return -1;
- }
}
- close(out);
+ else
+ close(out);
if (expect_status_report)
ret = receive_status(in, remote_refs);
@@ -649,7 +651,7 @@ int send_pack(struct send_pack_args *my_args,
conn = git_connect(fd, dest, args.receivepack, args.verbose ? CONNECT_VERBOSE : 0);
ret = do_send_pack(fd[0], fd[1], remote, dest, nr_heads, heads);
close(fd[0]);
- close(fd[1]);
+ /* do_send_pack always closes fd[1] */
ret |= finish_connect(conn);
return !!ret;
}
diff --git a/builtin-verify-tag.c b/builtin-verify-tag.c
index b3010f9827..f3ef11fa2d 100644
--- a/builtin-verify-tag.c
+++ b/builtin-verify-tag.c
@@ -45,7 +45,6 @@ static int run_gpg_verify(const char *buf, unsigned long size, int verbose)
memset(&gpg, 0, sizeof(gpg));
gpg.argv = args_gpg;
gpg.in = -1;
- gpg.out = 1;
args_gpg[2] = path;
if (start_command(&gpg))
return error("could not run gpg.");
diff --git a/bundle.c b/bundle.c
index 4352ce817f..0ba5df17e1 100644
--- a/bundle.c
+++ b/bundle.c
@@ -336,8 +336,9 @@ int create_bundle(struct bundle_header *header, const char *path,
close(rls.in);
if (finish_command(&rls))
return error ("pack-objects died");
-
- return bundle_to_stdout ? close(bundle_fd) : commit_lock_file(&lock);
+ if (!bundle_to_stdout)
+ commit_lock_file(&lock);
+ return 0;
}
int unbundle(struct bundle_header *header, int bundle_fd)
diff --git a/run-command.c b/run-command.c
index 2919330366..743757c36e 100644
--- a/run-command.c
+++ b/run-command.c
@@ -20,10 +20,18 @@ int start_command(struct child_process *cmd)
int need_in, need_out, need_err;
int fdin[2], fdout[2], fderr[2];
+ /*
+ * In case of errors we must keep the promise to close FDs
+ * that have been passed in via ->in and ->out.
+ */
+
need_in = !cmd->no_stdin && cmd->in < 0;
if (need_in) {
- if (pipe(fdin) < 0)
+ if (pipe(fdin) < 0) {
+ if (cmd->out > 0)
+ close(cmd->out);
return -ERR_RUN_COMMAND_PIPE;
+ }
cmd->in = fdin[1];
}
@@ -34,6 +42,8 @@ int start_command(struct child_process *cmd)
if (pipe(fdout) < 0) {
if (need_in)
close_pair(fdin);
+ else if (cmd->in)
+ close(cmd->in);
return -ERR_RUN_COMMAND_PIPE;
}
cmd->out = fdout[0];
@@ -44,8 +54,12 @@ int start_command(struct child_process *cmd)
if (pipe(fderr) < 0) {
if (need_in)
close_pair(fdin);
+ else if (cmd->in)
+ close(cmd->in);
if (need_out)
close_pair(fdout);
+ else if (cmd->out)
+ close(cmd->out);
return -ERR_RUN_COMMAND_PIPE;
}
cmd->err = fderr[0];
@@ -55,8 +69,12 @@ int start_command(struct child_process *cmd)
if (cmd->pid < 0) {
if (need_in)
close_pair(fdin);
+ else if (cmd->in)
+ close(cmd->in);
if (need_out)
close_pair(fdout);
+ else if (cmd->out)
+ close(cmd->out);
if (need_err)
close_pair(fderr);
return -ERR_RUN_COMMAND_FORK;
@@ -118,7 +136,7 @@ int start_command(struct child_process *cmd)
if (need_out)
close(fdout[1]);
- else if (cmd->out > 1)
+ else if (cmd->out)
close(cmd->out);
if (need_err)
diff --git a/run-command.h b/run-command.h
index e9c84d0363..debe3074b5 100644
--- a/run-command.h
+++ b/run-command.h
@@ -14,6 +14,24 @@ enum {
struct child_process {
const char **argv;
pid_t pid;
+ /*
+ * Using .in, .out, .err:
+ * - Specify 0 for no redirections (child inherits stdin, stdout,
+ * stderr from parent).
+ * - Specify -1 to have a pipe allocated as follows:
+ * .in: returns the writable pipe end; parent writes to it,
+ * the readable pipe end becomes child's stdin
+ * .out, .err: returns the readable pipe end; parent reads from
+ * it, the writable pipe end becomes child's stdout/stderr
+ * The caller of start_command() must close the returned FDs
+ * after it has completed reading from/writing to it!
+ * - Specify > 0 to set a channel to a particular FD as follows:
+ * .in: a readable FD, becomes child's stdin
+ * .out: a writable FD, becomes child's stdout/stderr
+ * .err > 0 not supported
+ * The specified FD is closed by start_command(), even in case
+ * of errors!
+ */
int in;
int out;
int err;