Skip to content

Commit

Permalink
upload-archive: fix infinite loop on Cygwin
Browse files Browse the repository at this point in the history
On Cygwin, poll() reports POLLIN even for file descriptors that have
reached their end.  This caused git upload-archive to be stuck in an
infinite loop, as it only looked at the POLLIN flag.

In addition to POLLIN, check if read() returned 0, which indicates
end-of-file, and keep looping only as long as at least one of the file
descriptors has input.  This lets the following command finish on its
own when run in a git repository on Cygwin, instead of it getting stuck
after printing all file names:

	$ git archive -v --remote . HEAD >/dev/null

Reported-by: Bob Kagy <bobkagy@gmail.com>
Signed-off-by: Rene Scharfe <rene.scharfe@lsrfire.ath.cx>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
  • Loading branch information
René Scharfe authored and Junio C Hamano committed Jun 18, 2009
1 parent 959e2e6 commit 1b19fa4
Showing 1 changed file with 7 additions and 5 deletions.
12 changes: 7 additions & 5 deletions builtin-upload-archive.c
Original file line number Diff line number Diff line change
Expand Up @@ -80,16 +80,17 @@ static void error_clnt(const char *fmt, ...)
die("sent error to the client: %s", buf);
}

static void process_input(int child_fd, int band)
static ssize_t process_input(int child_fd, int band)
{
char buf[16384];
ssize_t sz = read(child_fd, buf, sizeof(buf));
if (sz < 0) {
if (errno != EAGAIN && errno != EINTR)
error_clnt("read error: %s\n", strerror(errno));
return;
return sz;
}
send_sideband(1, band, buf, sz, LARGE_PACKET_MAX);
return sz;
}

int cmd_upload_archive(int argc, const char **argv, const char *prefix)
Expand Down Expand Up @@ -131,6 +132,7 @@ int cmd_upload_archive(int argc, const char **argv, const char *prefix)

while (1) {
struct pollfd pfd[2];
ssize_t processed[2] = { 0, 0 };
int status;

pfd[0].fd = fd1[0];
Expand All @@ -147,12 +149,12 @@ int cmd_upload_archive(int argc, const char **argv, const char *prefix)
}
if (pfd[0].revents & POLLIN)
/* Data stream ready */
process_input(pfd[0].fd, 1);
processed[0] = process_input(pfd[0].fd, 1);
if (pfd[1].revents & POLLIN)
/* Status stream ready */
process_input(pfd[1].fd, 2);
processed[1] = process_input(pfd[1].fd, 2);
/* Always finish to read data when available */
if ((pfd[0].revents | pfd[1].revents) & POLLIN)
if (processed[0] || processed[1])
continue;

if (waitpid(writer, &status, 0) < 0)
Expand Down

0 comments on commit 1b19fa4

Please sign in to comment.