diff options
author | Junio C Hamano <gitster@pobox.com> | 2015-03-25 12:54:27 -0700 |
---|---|---|
committer | Junio C Hamano <gitster@pobox.com> | 2015-03-25 12:54:27 -0700 |
commit | ea1fd481b4e689f143142662a82fb62c9b2efb65 (patch) | |
tree | a9e2475bf714d67eafee037aa710023495cad21e /run-command.c | |
parent | d78374e578a1837ee73c45f944c420c6f3f64deb (diff) | |
parent | c29b3962af3df80a43fab4ead4875bd2ca275e4c (diff) | |
download | git-ea1fd481b4e689f143142662a82fb62c9b2efb65.tar.gz |
Merge branch 'jk/run-command-capture'
The run-command interface was easy to abuse and make a pipe for us
to read from the process, wait for the process to finish and then
attempt to read its output, which is a pattern that lead to a
deadlock. Fix such uses by introducing a helper to do this
correctly (i.e. we need to read first and then wait the process to
finish) and also add code to prevent such abuse in the run-command
helper.
* jk/run-command-capture:
run-command: forbid using run_command with piped output
trailer: use capture_command
submodule: use capture_command
wt-status: use capture_command
run-command: introduce capture_command helper
wt_status: fix signedness mismatch in strbuf_read call
wt-status: don't flush before running "submodule status"
Diffstat (limited to 'run-command.c')
-rw-r--r-- | run-command.c | 23 |
1 files changed, 22 insertions, 1 deletions
diff --git a/run-command.c b/run-command.c index 3afb124c79..aad03ab705 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); @@ -829,3 +834,19 @@ int run_hook_le(const char *const *env, const char *name, ...) return ret; } + +int capture_command(struct child_process *cmd, struct strbuf *buf, size_t hint) +{ + cmd->out = -1; + if (start_command(cmd) < 0) + return -1; + + if (strbuf_read(buf, cmd->out, hint) < 0) { + close(cmd->out); + finish_command(cmd); /* throw away exit code */ + return -1; + } + + close(cmd->out); + return finish_command(cmd); +} |