run-command: handle dup2 and close errors in child

Signed-off-by: Brandon Williams <bmwill@google.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Brandon Williams committed Apr 19, 2017 at 16:13 UTC 53fa6753b30c4fb4ea768d16d41d723ea19a3b00
1 file changed +42 -16
run-command.c
+42 -16
@@ -213,6 +213,8 @@ static int child_notifier = -1;
213
214 enum child_errcode {
215 CHILD_ERR_CHDIR,
216 + CHILD_ERR_DUP2,
217 + CHILD_ERR_CLOSE,
218 CHILD_ERR_ENOENT,
219 CHILD_ERR_SILENT,
220 CHILD_ERR_ERRNO
@@ -235,6 +237,24 @@ static void child_die(enum child_errcode err)
237 _exit(1);
238 }
239
240 +static void child_dup2(int fd, int to)
241 +{
242 + if (dup2(fd, to) < 0)
243 + child_die(CHILD_ERR_DUP2);
244 +}
245 +
246 +static void child_close(int fd)
247 +{
248 + if (close(fd))
249 + child_die(CHILD_ERR_CLOSE);
250 +}
251 +
252 +static void child_close_pair(int fd[2])
253 +{
254 + child_close(fd[0]);
255 + child_close(fd[1]);
256 +}
257 +
258 /*
259 * parent will make it look like the child spewed a fatal error and died
260 * this is needed to prevent changes to t0061.
@@ -277,6 +297,12 @@ static void child_err_spew(struct child_process *cmd, struct child_err *cerr)
297 error_errno("exec '%s': cd to '%s' failed",
298 cmd->argv[0], cmd->dir);
299 break;
300 + case CHILD_ERR_DUP2:
301 + error_errno("dup2() in child failed");
302 + break;
303 + case CHILD_ERR_CLOSE:
304 + error_errno("close() in child failed");
305 + break;
306 case CHILD_ERR_ENOENT:
307 error_errno("cannot run %s", cmd->argv[0]);
308 break;
@@ -527,35 +553,35 @@ fail_pipe:
553 child_notifier = notify_pipe[1];
554
555 if (cmd->no_stdin)
530 - dup2(null_fd, 0);
556 + child_dup2(null_fd, 0);
557 else if (need_in) {
532 - dup2(fdin[0], 0);
533 - close_pair(fdin);
558 + child_dup2(fdin[0], 0);
559 + child_close_pair(fdin);
560 } else if (cmd->in) {
535 - dup2(cmd->in, 0);
536 - close(cmd->in);
561 + child_dup2(cmd->in, 0);
562 + child_close(cmd->in);
563 }
564
565 if (cmd->no_stderr)
540 - dup2(null_fd, 2);
566 + child_dup2(null_fd, 2);
567 else if (need_err) {
542 - dup2(fderr[1], 2);
543 - close_pair(fderr);
568 + child_dup2(fderr[1], 2);
569 + child_close_pair(fderr);
570 } else if (cmd->err > 1) {
545 - dup2(cmd->err, 2);
546 - close(cmd->err);
571 + child_dup2(cmd->err, 2);
572 + child_close(cmd->err);
573 }
574
575 if (cmd->no_stdout)
550 - dup2(null_fd, 1);
576 + child_dup2(null_fd, 1);
577 else if (cmd->stdout_to_stderr)
552 - dup2(2, 1);
578 + child_dup2(2, 1);
579 else if (need_out) {
554 - dup2(fdout[1], 1);
555 - close_pair(fdout);
580 + child_dup2(fdout[1], 1);
581 + child_close_pair(fdout);
582 } else if (cmd->out > 1) {
557 - dup2(cmd->out, 1);
558 - close(cmd->out);
583 + child_dup2(cmd->out, 1);
584 + child_close(cmd->out);
585 }
586
587 if (cmd->dir && chdir(cmd->dir))