r19309@catbus: nickm | 2008-04-11 16:02:07 -0400

Fix for epoll-on-linux bug (#1908866) where timeout values over (LONG_MAX-999)/HZ) (35 for me, or maybe 6 hours 50 min for some people, or maybe 3 hours 25 minutes for a special few) get treated as "wait forever".  This actually deserves to be fixed in the kernel, but even if it is we will need to support Linux versions with this bug.


svn:r709
This commit is contained in:
Nick Mathewson 2008-04-11 20:02:50 +00:00
parent 44ceb945a3
commit f9f4d4fe17
2 changed files with 15 additions and 0 deletions

View File

@ -64,6 +64,7 @@ Changes in current version:
o do not delete uninitialized timeout event in evdns
o Correct the documentation on buffer printf functions.
o Don't warn on unimplemented epoll_create(): this isn't a problem, just a reason to fall back to poll or select.
o Correctly handle timeouts larger than 35 minutes on Linux with epoll.c. This is probably a kernel defect, but we'll have to support old kernels anyway even if it gets fixed.
Changes in 1.4.0:

14
epoll.c
View File

@ -96,6 +96,14 @@ struct eventop epollops = {
#define NEVENT 32000
/* On Linux kernels at least up to 2.6.24.4, epoll can't handle timeout
* values bigger than (LONG_MAX - 999ULL)/HZ. HZ in the wild can be
* as big as 1000, and LONG_MAX can be as small as (1<<31)-1, so the
* largest number of msec we can support here is 2147482. Let's
* round that down by 47 seconds.
*/
#define MAX_EPOLL_TIMEOUT_MSEC (35*60*1000)
static void *
epoll_init(struct event_base *base)
{
@ -191,6 +199,12 @@ epoll_dispatch(struct event_base *base, void *arg, struct timeval *tv)
if (tv != NULL)
timeout = tv->tv_sec * 1000 + (tv->tv_usec + 999) / 1000;
if (timeout > MAX_EPOLL_TIMEOUT_MSEC) {
/* Linux kernels can wait forever if the timeout is too big;
* see comment on MAX_EPOLL_TIMEOUT_MSEC. */
timeout = MAX_EPOLL_TIMEOUT_MSEC;
}
res = epoll_wait(epollop->epfd, events, epollop->nevents, timeout);
if (res == -1) {