Because run_command both spawns and wait()s for the command
before returning control to the caller, any reads from the
pipes we open must necessarily happen after wait() returns.
This can lead to deadlock, as the child process may block on
writing to us while we are blocked waiting for it to exit.

Worse, it only happens when the child fills the pipe buffer,
which means that the problem may come and go depending on
the platform and the size of the output produced by the
child.

Let's detect and flag this dangerous construct so that we
can catch potential bugs early in the test suite rather than
having them happen in the field.

Signed-off-by: Jeff King <p...@peff.net>
---
 run-command.c | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/run-command.c b/run-command.c
index 3afb124..23636e0 100644
--- a/run-command.c
+++ b/run-command.c
@@ -557,7 +557,12 @@ int finish_command(struct child_process *cmd)
 
 int run_command(struct child_process *cmd)
 {
-       int code = start_command(cmd);
+       int code;
+
+       if (cmd->out < 0 || cmd->err < 0)
+               die("BUG: run_command with a pipe can cause deadlock");
+
+       code = start_command(cmd);
        if (code)
                return code;
        return finish_command(cmd);
-- 
2.3.3.618.ga041503
--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to