Git.pm: allow pipes to be closed prior to calling command_close_bidi_pipe
authorMichal Nazarewicz <mina86@mina86.com>
Tue, 12 Feb 2013 14:02:31 +0000 (15:02 +0100)
committerJunio C Hamano <gitster@pobox.com>
Tue, 12 Feb 2013 21:15:11 +0000 (13:15 -0800)
The command_close_bidi_pipe() function will insist on closing both
input and output pipes returned by command_bidi_pipe(). With this
change it is possible to close one of the pipes in advance and pass
undef as an argument.

Signed-off-by: Michal Nazarewicz <mina86@mina86.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
perl/Git.pm
index 2ccb95dc14a6ce6f7dbe906511c10295913e5a73..620e0f9e51100d0cba6593fb3c0236d79087f819 100644 (file)
@@ -426,12 +426,25 @@ sub command_bidi_pipe {
 currently it is simply the command name but in future the context might
 have more complicated structure.
 
 currently it is simply the command name but in future the context might
 have more complicated structure.
 
+C<PIPE_IN> and C<PIPE_OUT> may be C<undef> if they have been closed prior to
+calling this function.  This may be useful in a query-response type of
+commands where caller first writes a query and later reads response, eg:
+
+       my ($pid, $in, $out, $ctx) = $r->command_bidi_pipe('cat-file --batch-check');
+       print $out "000000000\n";
+       close $out;
+       while (<$in>) { ... }
+       $r->command_close_bidi_pipe($pid, $in, undef, $ctx);
+
+This idiom may prevent potential dead locks caused by data sent to the output
+pipe not being flushed and thus not reaching the executed command.
+
 =cut
 
 sub command_close_bidi_pipe {
        local $?;
        my ($self, $pid, $in, $out, $ctx) = _maybe_self(@_);
 =cut
 
 sub command_close_bidi_pipe {
        local $?;
        my ($self, $pid, $in, $out, $ctx) = _maybe_self(@_);
-       _cmd_close($ctx, $in, $out);
+       _cmd_close($ctx, (grep { defined } ($in, $out)));
        waitpid $pid, 0;
        if ($? >> 8) {
                throw Git::Error::Command($ctx, $? >>8);
        waitpid $pid, 0;
        if ($? >> 8) {
                throw Git::Error::Command($ctx, $? >>8);