1
0
Fork 0
mirror of https://github.com/git/git.git synced 2024-11-13 20:53:02 +01:00

Merge branch 'js/run-command'

* js/run-command:
  start_command(), if .in/.out > 0, closes file descriptors, not the callers
  start_command(), .in/.out/.err = -1: Callers must close the file descriptor
This commit is contained in:
Junio C Hamano 2008-02-27 11:55:32 -08:00
commit f79ff5c975
8 changed files with 58 additions and 22 deletions

View file

@ -538,8 +538,10 @@ static int get_pack(int xd[2], char **pack_lockfile)
cmd.git_cmd = 1; cmd.git_cmd = 1;
if (start_command(&cmd)) if (start_command(&cmd))
die("fetch-pack: unable to fork off %s", argv[0]); die("fetch-pack: unable to fork off %s", argv[0]);
if (do_keep && pack_lockfile) if (do_keep && pack_lockfile) {
*pack_lockfile = index_pack_lockfile(cmd.out); *pack_lockfile = index_pack_lockfile(cmd.out);
close(cmd.out);
}
if (finish_command(&cmd)) if (finish_command(&cmd))
die("%s failed", argv[0]); die("%s failed", argv[0]);

View file

@ -71,6 +71,7 @@ static int pack_objects(int fd, struct ref *refs)
refs = refs->next; refs = refs->next;
} }
close(po.in);
if (finish_command(&po)) if (finish_command(&po))
return error("pack-objects died with strange error"); return error("pack-objects died with strange error");
return 0; return 0;
@ -403,12 +404,15 @@ static int do_send_pack(int in, int out, struct remote *remote, const char *dest
if (!remote_tail) if (!remote_tail)
remote_tail = &remote_refs; remote_tail = &remote_refs;
if (match_refs(local_refs, remote_refs, &remote_tail, if (match_refs(local_refs, remote_refs, &remote_tail,
nr_refspec, refspec, flags)) nr_refspec, refspec, flags)) {
close(out);
return -1; return -1;
}
if (!remote_refs) { if (!remote_refs) {
fprintf(stderr, "No refs in common and none specified; doing nothing.\n" fprintf(stderr, "No refs in common and none specified; doing nothing.\n"
"Perhaps you should specify a branch such as 'master'.\n"); "Perhaps you should specify a branch such as 'master'.\n");
close(out);
return 0; return 0;
} }
@ -495,11 +499,10 @@ static int do_send_pack(int in, int out, struct remote *remote, const char *dest
packet_flush(out); packet_flush(out);
if (new_refs && !args.dry_run) { if (new_refs && !args.dry_run) {
if (pack_objects(out, remote_refs) < 0) { if (pack_objects(out, remote_refs) < 0)
close(out);
return -1; return -1;
} }
} else
close(out); close(out);
if (expect_status_report) if (expect_status_report)
@ -648,7 +651,7 @@ int send_pack(struct send_pack_args *my_args,
conn = git_connect(fd, dest, args.receivepack, args.verbose ? CONNECT_VERBOSE : 0); 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); ret = do_send_pack(fd[0], fd[1], remote, dest, nr_heads, heads);
close(fd[0]); close(fd[0]);
close(fd[1]); /* do_send_pack always closes fd[1] */
ret |= finish_connect(conn); ret |= finish_connect(conn);
return !!ret; return !!ret;
} }

View file

@ -226,12 +226,13 @@ static int do_sign(struct strbuf *buffer)
if (write_in_full(gpg.in, buffer->buf, buffer->len) != buffer->len) { if (write_in_full(gpg.in, buffer->buf, buffer->len) != buffer->len) {
close(gpg.in); close(gpg.in);
close(gpg.out);
finish_command(&gpg); finish_command(&gpg);
return error("gpg did not accept the tag data"); return error("gpg did not accept the tag data");
} }
close(gpg.in); close(gpg.in);
gpg.close_in = 0;
len = strbuf_read(buffer, gpg.out, 1024); len = strbuf_read(buffer, gpg.out, 1024);
close(gpg.out);
if (finish_command(&gpg) || !len || len < 0) if (finish_command(&gpg) || !len || len < 0)
return error("gpg failed to sign the tag"); return error("gpg failed to sign the tag");

View file

@ -45,14 +45,12 @@ static int run_gpg_verify(const char *buf, unsigned long size, int verbose)
memset(&gpg, 0, sizeof(gpg)); memset(&gpg, 0, sizeof(gpg));
gpg.argv = args_gpg; gpg.argv = args_gpg;
gpg.in = -1; gpg.in = -1;
gpg.out = 1;
args_gpg[2] = path; args_gpg[2] = path;
if (start_command(&gpg)) if (start_command(&gpg))
return error("could not run gpg."); return error("could not run gpg.");
write_in_full(gpg.in, buf, len); write_in_full(gpg.in, buf, len);
close(gpg.in); close(gpg.in);
gpg.close_in = 0;
ret = finish_command(&gpg); ret = finish_command(&gpg);
unlink(path); unlink(path);

View file

@ -333,10 +333,12 @@ int create_bundle(struct bundle_header *header, const char *path,
write_or_die(rls.in, sha1_to_hex(object->sha1), 40); write_or_die(rls.in, sha1_to_hex(object->sha1), 40);
write_or_die(rls.in, "\n", 1); write_or_die(rls.in, "\n", 1);
} }
close(rls.in);
if (finish_command(&rls)) if (finish_command(&rls))
return error ("pack-objects died"); return error ("pack-objects died");
if (!bundle_to_stdout)
return bundle_to_stdout ? close(bundle_fd) : commit_lock_file(&lock); commit_lock_file(&lock);
return 0;
} }
int unbundle(struct bundle_header *header, int bundle_fd) int unbundle(struct bundle_header *header, int bundle_fd)

View file

@ -132,6 +132,7 @@ static int run_hook(const char *hook_name)
break; break;
} }
} }
close(proc.in);
return hook_status(finish_command(&proc), hook_name); return hook_status(finish_command(&proc), hook_name);
} }
@ -414,6 +415,7 @@ static const char *unpack(void)
if (start_command(&ip)) if (start_command(&ip))
return "index-pack fork failed"; return "index-pack fork failed";
pack_lockfile = index_pack_lockfile(ip.out); pack_lockfile = index_pack_lockfile(ip.out);
close(ip.out);
status = finish_command(&ip); status = finish_command(&ip);
if (!status) { if (!status) {
reprepare_packed_git(); reprepare_packed_git();

View file

@ -20,12 +20,19 @@ int start_command(struct child_process *cmd)
int need_in, need_out, need_err; int need_in, need_out, need_err;
int fdin[2], fdout[2], fderr[2]; 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; need_in = !cmd->no_stdin && cmd->in < 0;
if (need_in) { if (need_in) {
if (pipe(fdin) < 0) if (pipe(fdin) < 0) {
if (cmd->out > 0)
close(cmd->out);
return -ERR_RUN_COMMAND_PIPE; return -ERR_RUN_COMMAND_PIPE;
}
cmd->in = fdin[1]; cmd->in = fdin[1];
cmd->close_in = 1;
} }
need_out = !cmd->no_stdout need_out = !cmd->no_stdout
@ -35,10 +42,11 @@ int start_command(struct child_process *cmd)
if (pipe(fdout) < 0) { if (pipe(fdout) < 0) {
if (need_in) if (need_in)
close_pair(fdin); close_pair(fdin);
else if (cmd->in)
close(cmd->in);
return -ERR_RUN_COMMAND_PIPE; return -ERR_RUN_COMMAND_PIPE;
} }
cmd->out = fdout[0]; cmd->out = fdout[0];
cmd->close_out = 1;
} }
need_err = !cmd->no_stderr && cmd->err < 0; need_err = !cmd->no_stderr && cmd->err < 0;
@ -46,8 +54,12 @@ int start_command(struct child_process *cmd)
if (pipe(fderr) < 0) { if (pipe(fderr) < 0) {
if (need_in) if (need_in)
close_pair(fdin); close_pair(fdin);
else if (cmd->in)
close(cmd->in);
if (need_out) if (need_out)
close_pair(fdout); close_pair(fdout);
else if (cmd->out)
close(cmd->out);
return -ERR_RUN_COMMAND_PIPE; return -ERR_RUN_COMMAND_PIPE;
} }
cmd->err = fderr[0]; cmd->err = fderr[0];
@ -57,8 +69,12 @@ int start_command(struct child_process *cmd)
if (cmd->pid < 0) { if (cmd->pid < 0) {
if (need_in) if (need_in)
close_pair(fdin); close_pair(fdin);
else if (cmd->in)
close(cmd->in);
if (need_out) if (need_out)
close_pair(fdout); close_pair(fdout);
else if (cmd->out)
close(cmd->out);
if (need_err) if (need_err)
close_pair(fderr); close_pair(fderr);
return -ERR_RUN_COMMAND_FORK; return -ERR_RUN_COMMAND_FORK;
@ -120,7 +136,7 @@ int start_command(struct child_process *cmd)
if (need_out) if (need_out)
close(fdout[1]); close(fdout[1]);
else if (cmd->out > 1) else if (cmd->out)
close(cmd->out); close(cmd->out);
if (need_err) if (need_err)
@ -157,10 +173,6 @@ static int wait_or_whine(pid_t pid)
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); return wait_or_whine(cmd->pid);
} }

View file

@ -14,13 +14,29 @@ enum {
struct child_process { struct child_process {
const char **argv; const char **argv;
pid_t pid; 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 in;
int out; int out;
int err; int err;
const char *dir; const char *dir;
const char *const *env; const char *const *env;
unsigned close_in:1;
unsigned close_out:1;
unsigned no_stdin:1; unsigned no_stdin:1;
unsigned no_stdout:1; unsigned no_stdout:1;
unsigned no_stderr:1; unsigned no_stderr:1;