receive-pack: close sideband fd on early pack errors
commit49ecfa13fe6fb9ccb7c4771126872515340c328b
authorJeff King <peff@peff.net>
Fri, 19 Apr 2013 21:24:29 +0000 (19 17:24 -0400)
committerJunio C Hamano <gitster@pobox.com>
Fri, 19 Apr 2013 21:43:24 +0000 (19 14:43 -0700)
tree6b4bf8187a81075b5facf3fbbf2c99d95b000acf
parent04a74b6cfa5ef4870263f84ac94a488d9f2ef14a
receive-pack: close sideband fd on early pack errors

Since commit a22e6f8 (receive-pack: send pack-processing
stderr over sideband, 2012-09-21), receive-pack will start
an async sideband thread to copy the stderr from our
index-pack or unpack-objects child to the client. We hand
the thread's input descriptor to unpack(), which puts it in
the "err" member of the "struct child_process".

After unpack() returns, we use finish_async() to reap the
sideband thread. The thread is only ready to die when it
gets EOF on its pipe, which is connected to the err
descriptor. So we expect all of the write ends of that pipe
to be closed as part of unpack().

Normally, this works fine. After start_command forks, it
closes the parent copy of the descriptor. Then once the
child exits (whether it was successful or not), that closes
the only remaining writer.

However, there is one code-path in unpack() that does not
handle this. Before we decide which of unpack-objects or
index-pack to use, we read the pack header ourselves to see
how many objects it contains. If there is an error here, we
exit without running either sub-command, the pipe descriptor
remains open, and we are in a deadlock, waiting for the
sideband thread to die (which is in turn waiting for us to
close the pipe).

We can fix this by making sure that unpack() always closes
the pipe before returning.

Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
builtin/receive-pack.c