Skip to content

Commit f79ff5c

Browse files
committed
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
2 parents 860cc3a + c20181e commit f79ff5c

File tree

8 files changed

+58
-22
lines changed

8 files changed

+58
-22
lines changed

builtin-fetch-pack.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -538,8 +538,10 @@ static int get_pack(int xd[2], char **pack_lockfile)
538538
cmd.git_cmd = 1;
539539
if (start_command(&cmd))
540540
die("fetch-pack: unable to fork off %s", argv[0]);
541-
if (do_keep && pack_lockfile)
541+
if (do_keep && pack_lockfile) {
542542
*pack_lockfile = index_pack_lockfile(cmd.out);
543+
close(cmd.out);
544+
}
543545

544546
if (finish_command(&cmd))
545547
die("%s failed", argv[0]);

builtin-send-pack.c

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ static int pack_objects(int fd, struct ref *refs)
7171
refs = refs->next;
7272
}
7373

74+
close(po.in);
7475
if (finish_command(&po))
7576
return error("pack-objects died with strange error");
7677
return 0;
@@ -403,12 +404,15 @@ static int do_send_pack(int in, int out, struct remote *remote, const char *dest
403404
if (!remote_tail)
404405
remote_tail = &remote_refs;
405406
if (match_refs(local_refs, remote_refs, &remote_tail,
406-
nr_refspec, refspec, flags))
407+
nr_refspec, refspec, flags)) {
408+
close(out);
407409
return -1;
410+
}
408411

409412
if (!remote_refs) {
410413
fprintf(stderr, "No refs in common and none specified; doing nothing.\n"
411414
"Perhaps you should specify a branch such as 'master'.\n");
415+
close(out);
412416
return 0;
413417
}
414418

@@ -495,12 +499,11 @@ static int do_send_pack(int in, int out, struct remote *remote, const char *dest
495499

496500
packet_flush(out);
497501
if (new_refs && !args.dry_run) {
498-
if (pack_objects(out, remote_refs) < 0) {
499-
close(out);
502+
if (pack_objects(out, remote_refs) < 0)
500503
return -1;
501-
}
502504
}
503-
close(out);
505+
else
506+
close(out);
504507

505508
if (expect_status_report)
506509
ret = receive_status(in, remote_refs);
@@ -648,7 +651,7 @@ int send_pack(struct send_pack_args *my_args,
648651
conn = git_connect(fd, dest, args.receivepack, args.verbose ? CONNECT_VERBOSE : 0);
649652
ret = do_send_pack(fd[0], fd[1], remote, dest, nr_heads, heads);
650653
close(fd[0]);
651-
close(fd[1]);
654+
/* do_send_pack always closes fd[1] */
652655
ret |= finish_connect(conn);
653656
return !!ret;
654657
}

builtin-tag.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -226,12 +226,13 @@ static int do_sign(struct strbuf *buffer)
226226

227227
if (write_in_full(gpg.in, buffer->buf, buffer->len) != buffer->len) {
228228
close(gpg.in);
229+
close(gpg.out);
229230
finish_command(&gpg);
230231
return error("gpg did not accept the tag data");
231232
}
232233
close(gpg.in);
233-
gpg.close_in = 0;
234234
len = strbuf_read(buffer, gpg.out, 1024);
235+
close(gpg.out);
235236

236237
if (finish_command(&gpg) || !len || len < 0)
237238
return error("gpg failed to sign the tag");

builtin-verify-tag.c

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,14 +45,12 @@ static int run_gpg_verify(const char *buf, unsigned long size, int verbose)
4545
memset(&gpg, 0, sizeof(gpg));
4646
gpg.argv = args_gpg;
4747
gpg.in = -1;
48-
gpg.out = 1;
4948
args_gpg[2] = path;
5049
if (start_command(&gpg))
5150
return error("could not run gpg.");
5251

5352
write_in_full(gpg.in, buf, len);
5453
close(gpg.in);
55-
gpg.close_in = 0;
5654
ret = finish_command(&gpg);
5755

5856
unlink(path);

bundle.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -333,10 +333,12 @@ int create_bundle(struct bundle_header *header, const char *path,
333333
write_or_die(rls.in, sha1_to_hex(object->sha1), 40);
334334
write_or_die(rls.in, "\n", 1);
335335
}
336+
close(rls.in);
336337
if (finish_command(&rls))
337338
return error ("pack-objects died");
338-
339-
return bundle_to_stdout ? close(bundle_fd) : commit_lock_file(&lock);
339+
if (!bundle_to_stdout)
340+
commit_lock_file(&lock);
341+
return 0;
340342
}
341343

342344
int unbundle(struct bundle_header *header, int bundle_fd)

receive-pack.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,7 @@ static int run_hook(const char *hook_name)
132132
break;
133133
}
134134
}
135+
close(proc.in);
135136
return hook_status(finish_command(&proc), hook_name);
136137
}
137138

@@ -414,6 +415,7 @@ static const char *unpack(void)
414415
if (start_command(&ip))
415416
return "index-pack fork failed";
416417
pack_lockfile = index_pack_lockfile(ip.out);
418+
close(ip.out);
417419
status = finish_command(&ip);
418420
if (!status) {
419421
reprepare_packed_git();

run-command.c

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -20,12 +20,19 @@ int start_command(struct child_process *cmd)
2020
int need_in, need_out, need_err;
2121
int fdin[2], fdout[2], fderr[2];
2222

23+
/*
24+
* In case of errors we must keep the promise to close FDs
25+
* that have been passed in via ->in and ->out.
26+
*/
27+
2328
need_in = !cmd->no_stdin && cmd->in < 0;
2429
if (need_in) {
25-
if (pipe(fdin) < 0)
30+
if (pipe(fdin) < 0) {
31+
if (cmd->out > 0)
32+
close(cmd->out);
2633
return -ERR_RUN_COMMAND_PIPE;
34+
}
2735
cmd->in = fdin[1];
28-
cmd->close_in = 1;
2936
}
3037

3138
need_out = !cmd->no_stdout
@@ -35,19 +42,24 @@ int start_command(struct child_process *cmd)
3542
if (pipe(fdout) < 0) {
3643
if (need_in)
3744
close_pair(fdin);
45+
else if (cmd->in)
46+
close(cmd->in);
3847
return -ERR_RUN_COMMAND_PIPE;
3948
}
4049
cmd->out = fdout[0];
41-
cmd->close_out = 1;
4250
}
4351

4452
need_err = !cmd->no_stderr && cmd->err < 0;
4553
if (need_err) {
4654
if (pipe(fderr) < 0) {
4755
if (need_in)
4856
close_pair(fdin);
57+
else if (cmd->in)
58+
close(cmd->in);
4959
if (need_out)
5060
close_pair(fdout);
61+
else if (cmd->out)
62+
close(cmd->out);
5163
return -ERR_RUN_COMMAND_PIPE;
5264
}
5365
cmd->err = fderr[0];
@@ -57,8 +69,12 @@ int start_command(struct child_process *cmd)
5769
if (cmd->pid < 0) {
5870
if (need_in)
5971
close_pair(fdin);
72+
else if (cmd->in)
73+
close(cmd->in);
6074
if (need_out)
6175
close_pair(fdout);
76+
else if (cmd->out)
77+
close(cmd->out);
6278
if (need_err)
6379
close_pair(fderr);
6480
return -ERR_RUN_COMMAND_FORK;
@@ -120,7 +136,7 @@ int start_command(struct child_process *cmd)
120136

121137
if (need_out)
122138
close(fdout[1]);
123-
else if (cmd->out > 1)
139+
else if (cmd->out)
124140
close(cmd->out);
125141

126142
if (need_err)
@@ -157,10 +173,6 @@ static int wait_or_whine(pid_t pid)
157173

158174
int finish_command(struct child_process *cmd)
159175
{
160-
if (cmd->close_in)
161-
close(cmd->in);
162-
if (cmd->close_out)
163-
close(cmd->out);
164176
return wait_or_whine(cmd->pid);
165177
}
166178

run-command.h

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,29 @@ enum {
1414
struct child_process {
1515
const char **argv;
1616
pid_t pid;
17+
/*
18+
* Using .in, .out, .err:
19+
* - Specify 0 for no redirections (child inherits stdin, stdout,
20+
* stderr from parent).
21+
* - Specify -1 to have a pipe allocated as follows:
22+
* .in: returns the writable pipe end; parent writes to it,
23+
* the readable pipe end becomes child's stdin
24+
* .out, .err: returns the readable pipe end; parent reads from
25+
* it, the writable pipe end becomes child's stdout/stderr
26+
* The caller of start_command() must close the returned FDs
27+
* after it has completed reading from/writing to it!
28+
* - Specify > 0 to set a channel to a particular FD as follows:
29+
* .in: a readable FD, becomes child's stdin
30+
* .out: a writable FD, becomes child's stdout/stderr
31+
* .err > 0 not supported
32+
* The specified FD is closed by start_command(), even in case
33+
* of errors!
34+
*/
1735
int in;
1836
int out;
1937
int err;
2038
const char *dir;
2139
const char *const *env;
22-
unsigned close_in:1;
23-
unsigned close_out:1;
2440
unsigned no_stdin:1;
2541
unsigned no_stdout:1;
2642
unsigned no_stderr:1;

0 commit comments

Comments
 (0)