poll: honor the timeout on Win32

Ensure that when passing a pipe, the gnulib poll replacement will not
return 0 before the timeout has passed.

Not obeying the timeout (and merely returning 0) causes pathological
behavior when preparing a packfile for a repository and taking a
long time to do so.  If poll were to return 0 immediately, this would
cause keep-alives to get sent as quickly as possible until the packfile
was created.  Such deviance from the standard would cause megabytes (or
more) of keep-alive packets to be sent.

GetTickCount is used as it is efficient, stable and monotonically
increasing.  (Neither GetSystemTime nor QueryPerformanceCounter have
all three of these properties.)
This commit is contained in:
Edward Thomson
2015-03-18 10:10:41 -04:00
committed by Johannes Schindelin
parent 5adb572fa4
commit 1d99025822

View File

@@ -446,7 +446,7 @@ poll (struct pollfd *pfd, nfds_t nfd, int timeout)
static HANDLE hEvent;
WSANETWORKEVENTS ev;
HANDLE h, handle_array[FD_SETSIZE + 2];
DWORD ret, wait_timeout, nhandles;
DWORD ret, wait_timeout, nhandles, start = 0, elapsed, orig_timeout = 0;
fd_set rfds, wfds, xfds;
BOOL poll_again;
MSG msg;
@@ -459,6 +459,12 @@ poll (struct pollfd *pfd, nfds_t nfd, int timeout)
return -1;
}
if (timeout != INFTIM)
{
orig_timeout = timeout;
start = GetTickCount();
}
if (!hEvent)
hEvent = CreateEvent (NULL, FALSE, FALSE, NULL);
@@ -603,7 +609,13 @@ restart:
rc++;
}
if (!rc && timeout == INFTIM)
if (!rc && orig_timeout && timeout != INFTIM)
{
elapsed = GetTickCount() - start;
timeout = elapsed >= orig_timeout ? 0 : orig_timeout - elapsed;
}
if (!rc && timeout)
{
SleepEx (1, TRUE);
goto restart;