run-command: handle dup2 and close errors in child
authorBrandon Williams <bmwill@google.com>
Wed, 19 Apr 2017 23:13:25 +0000 (16:13 -0700)
committerJunio C Hamano <gitster@pobox.com>
Fri, 21 Apr 2017 00:55:32 +0000 (17:55 -0700)
Signed-off-by: Brandon Williams <bmwill@google.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
run-command.c
index 1f15714b157db79231d7cfaf6f90e354b855647d..615b6e9c9c77f069254314b93583f56df1a1c0b7 100644 (file)
@@ -213,6 +213,8 @@ static int child_notifier = -1;
 
 enum child_errcode {
        CHILD_ERR_CHDIR,
+       CHILD_ERR_DUP2,
+       CHILD_ERR_CLOSE,
        CHILD_ERR_ENOENT,
        CHILD_ERR_SILENT,
        CHILD_ERR_ERRNO
@@ -235,6 +237,24 @@ static void child_die(enum child_errcode err)
        _exit(1);
 }
 
+static void child_dup2(int fd, int to)
+{
+       if (dup2(fd, to) < 0)
+               child_die(CHILD_ERR_DUP2);
+}
+
+static void child_close(int fd)
+{
+       if (close(fd))
+               child_die(CHILD_ERR_CLOSE);
+}
+
+static void child_close_pair(int fd[2])
+{
+       child_close(fd[0]);
+       child_close(fd[1]);
+}
+
 /*
  * parent will make it look like the child spewed a fatal error and died
  * 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)
                error_errno("exec '%s': cd to '%s' failed",
                            cmd->argv[0], cmd->dir);
                break;
+       case CHILD_ERR_DUP2:
+               error_errno("dup2() in child failed");
+               break;
+       case CHILD_ERR_CLOSE:
+               error_errno("close() in child failed");
+               break;
        case CHILD_ERR_ENOENT:
                error_errno("cannot run %s", cmd->argv[0]);
                break;
@@ -527,35 +553,35 @@ int start_command(struct child_process *cmd)
                child_notifier = notify_pipe[1];
 
                if (cmd->no_stdin)
-                       dup2(null_fd, 0);
+                       child_dup2(null_fd, 0);
                else if (need_in) {
-                       dup2(fdin[0], 0);
-                       close_pair(fdin);
+                       child_dup2(fdin[0], 0);
+                       child_close_pair(fdin);
                } else if (cmd->in) {
-                       dup2(cmd->in, 0);
-                       close(cmd->in);
+                       child_dup2(cmd->in, 0);
+                       child_close(cmd->in);
                }
 
                if (cmd->no_stderr)
-                       dup2(null_fd, 2);
+                       child_dup2(null_fd, 2);
                else if (need_err) {
-                       dup2(fderr[1], 2);
-                       close_pair(fderr);
+                       child_dup2(fderr[1], 2);
+                       child_close_pair(fderr);
                } else if (cmd->err > 1) {
-                       dup2(cmd->err, 2);
-                       close(cmd->err);
+                       child_dup2(cmd->err, 2);
+                       child_close(cmd->err);
                }
 
                if (cmd->no_stdout)
-                       dup2(null_fd, 1);
+                       child_dup2(null_fd, 1);
                else if (cmd->stdout_to_stderr)
-                       dup2(2, 1);
+                       child_dup2(2, 1);
                else if (need_out) {
-                       dup2(fdout[1], 1);
-                       close_pair(fdout);
+                       child_dup2(fdout[1], 1);
+                       child_close_pair(fdout);
                } else if (cmd->out > 1) {
-                       dup2(cmd->out, 1);
-                       close(cmd->out);
+                       child_dup2(cmd->out, 1);
+                       child_close(cmd->out);
                }
 
                if (cmd->dir && chdir(cmd->dir))