summaryrefslogtreecommitdiff
path: root/run-command.c
diff options
context:
space:
mode:
authorJunio C Hamano <gitster@pobox.com>2015-03-25 19:54:27 (GMT)
committerJunio C Hamano <gitster@pobox.com>2015-03-25 19:54:27 (GMT)
commitea1fd481b4e689f143142662a82fb62c9b2efb65 (patch)
treea9e2475bf714d67eafee037aa710023495cad21e /run-command.c
parentd78374e578a1837ee73c45f944c420c6f3f64deb (diff)
parentc29b3962af3df80a43fab4ead4875bd2ca275e4c (diff)
downloadgit-ea1fd481b4e689f143142662a82fb62c9b2efb65.zip
git-ea1fd481b4e689f143142662a82fb62c9b2efb65.tar.gz
git-ea1fd481b4e689f143142662a82fb62c9b2efb65.tar.bz2
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.c23
1 files changed, 22 insertions, 1 deletions
diff --git a/run-command.c b/run-command.c
index 3afb124..aad03ab 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);
+}