I ran into what I think is a bug: sh$ git fetch 0<&- (i.e. run git-fetch with stdin closed.) It aborts with: fatal: read error (Bad file descriptor) I think the problem arises from the use of dup2+close in start_command(). It wants to rename a pipe file descriptor to 0, so it does dup2(from, to); close(from); ... but in this case from == to == 0, so dup2(0, 0); close(0); just ends up closing the pipe. The patch below fixes the problem for me. >From 78446c82131a5ca7f22f92bc32d7f3036bba9629 Mon Sep 17 00:00:00 2001 From: Karl Chen <quarl@xxxxxxxxx> Date: Mon, 25 Aug 2008 01:09:08 -0700 Subject: [PATCH] Fix start_command() pipe bug when stdin is closed. When intending to rename a fd to 0, if the fd is already 0, then do nothing, instead of dup2(0,0); close(0); The problematic behavior could be seen thus: git-fetch 0<&- Signed-off-by: Karl Chen <quarl@xxxxxxxxx> --- run-command.c | 29 +++++++++++++++++------------ 1 files changed, 17 insertions(+), 12 deletions(-) diff --git a/run-command.c b/run-command.c index caab374..b4bd80f 100644 --- a/run-command.c +++ b/run-command.c @@ -8,11 +8,18 @@ static inline void close_pair(int fd[2]) close(fd[1]); } +static inline void rename_fd(int from, int to) +{ + if (from != to) { + dup2(from, to); + close(from); + } +} + static inline void dup_devnull(int to) { int fd = open("/dev/null", O_RDWR); - dup2(fd, to); - close(fd); + rename_fd(fd, to); } int start_command(struct child_process *cmd) @@ -74,18 +81,17 @@ int start_command(struct child_process *cmd) if (cmd->no_stdin) dup_devnull(0); else if (need_in) { - dup2(fdin[0], 0); - close_pair(fdin); + rename_fd(fdin[0], 0); + close(fdin[1]); } else if (cmd->in) { - dup2(cmd->in, 0); - close(cmd->in); + rename_fd(cmd->in, 0); } if (cmd->no_stderr) dup_devnull(2); else if (need_err) { - dup2(fderr[1], 2); - close_pair(fderr); + rename_fd(fderr[1], 2); + close(fderr[0]); } if (cmd->no_stdout) @@ -93,11 +99,10 @@ int start_command(struct child_process *cmd) else if (cmd->stdout_to_stderr) dup2(2, 1); else if (need_out) { - dup2(fdout[1], 1); - close_pair(fdout); + rename_fd(fdout[1], 1); + close(fdout[0]); } else if (cmd->out > 1) { - dup2(cmd->out, 1); - close(cmd->out); + rename_fd(cmd->out, 1); } if (cmd->dir && chdir(cmd->dir)) -- 1.5.6.2 -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html