1 // Copyright 2011 Keith Rarick. See file COPYING for details.
4 #include <sys/resource.h>
8 static void handleev(const int fd
, const short ev
, Socket
*s
);
9 static void nudge_fd_limit();
13 static struct timeval ival
;
17 sockinit(Handle f
, void *x
, int64 i
)
21 init_timeval(&ival
, i
);
28 sockwant(Socket
*s
, int rw
)
33 r
= event_del(&s
->evq
);
44 // fake a global timeout with libevent
45 event_set(&s
->evq
, s
->fd
, EV_READ
|EV_PERSIST
, (evh
)handleev
, s
);
46 return event_add(&s
->evq
, &ival
);
54 event_set(&s
->evq
, s
->fd
, mask
|EV_PERSIST
, (evh
)handleev
, s
);
55 return event_add(&s
->evq
, 0);
69 handleev(const int fd
, const short ev
, Socket
*s
)
73 // libevent removes the fd if it timed out, so put it back
74 event_add(&s
->evq
, &ival
);
87 /* This is a workaround for a mystifying workaround in libevent's epoll
88 * implementation. The epoll_init() function creates an epoll fd with space to
89 * handle RLIMIT_NOFILE - 1 fds, accompanied by the following puzzling comment:
90 * "Solaris is somewhat retarded - it's important to drop backwards
91 * compatibility when making changes. So, don't dare to put rl.rlim_cur here."
92 * This is presumably to work around a bug in Solaris, but it has the
93 * unfortunate side-effect of causing epoll_ctl() (and, therefore, event_add())
94 * to fail for a valid fd if we have hit the limit of open fds. That makes it
95 * hard to provide reasonable behavior in that situation. So, let's reduce the
96 * real value of RLIMIT_NOFILE by one, after epoll_init() has run. */
103 r
= getrlimit(RLIMIT_NOFILE
, &rl
);
104 if (r
!= 0) twarn("getrlimit(RLIMIT_NOFILE)"), exit(2);
108 r
= setrlimit(RLIMIT_NOFILE
, &rl
);
109 if (r
!= 0) twarn("setrlimit(RLIMIT_NOFILE)"), exit(2);