Skip to content
  • Jeff King's avatar
    run-command: introduce capture_command helper · 911ec99b
    Jeff King authored and Junio C Hamano's avatar Junio C Hamano committed
    
    
    Something as simple as reading the stdout from a command
    turns out to be rather hard to do right. Doing:
    
      cmd.out = -1;
      run_command(&cmd);
      strbuf_read(&buf, cmd.out, 0);
    
    can result in deadlock if the child process produces a large
    amount of output. What happens is:
    
      1. The parent spawns the child with its stdout connected
         to a pipe, of which the parent is the sole reader.
    
      2. The parent calls wait(), blocking until the child exits.
    
      3. The child writes to stdout. If it writes more data than
         the OS pipe buffer can hold, the write() call will
         block.
    
    This is a deadlock; the parent is waiting for the child to
    exit, and the child is waiting for the parent to call
    read().
    
    So we might try instead:
    
      start_command(&cmd);
      strbuf_read(&buf, cmd.out, 0);
      finish_command(&cmd);
    
    But that is not quite right either. We are examining cmd.out
    and running finish_command whether start_command succeeded
    or not, which is wrong. Moreover, these snippets do not do
    any error handling. If our read() fails, we must make sure
    to still call finish_command (to reap the child process).
    And both snippets failed to close the cmd.out descriptor,
    which they must do (provided start_command succeeded).
    
    Let's introduce a run-command helper that can make this a
    bit simpler for callers to get right.
    
    Signed-off-by: default avatarJeff King <peff@peff.net>
    Signed-off-by: default avatarJunio C Hamano <gitster@pobox.com>
    911ec99b