#include <sys/event.h>
-#define KE_LENGTH 128
-
/* jlemon goofed up and didn't add EV_SET until fbsd 4.3 */
#ifndef EV_SET
static struct timespec zero_timespec;
static struct kevent *kqlst; /* kevent buffer */
+static struct kevent *kqout; /* kevent output buffer */
static int kqmax; /* max structs to buffer */
static int kqoff; /* offset into the buffer */
if(++kqoff == kqmax)
{
- int ret;
-
- ret = kevent(kq, kqlst, kqoff, NULL, 0, &zero_timespec);
- /* jdc -- someone needs to do error checking... */
- if(ret == -1)
+ int ret, i;
+
+ /* Add them one at a time, because there may be
+ * already closed fds in it. The kernel will try
+ * to report invalid fds in the output; if there
+ * is no space, it silently stops processing the
+ * array at that point. We cannot give output space
+ * because that would also return events we cannot
+ * process at this point.
+ */
+ for (i = 0; i < kqoff; i++)
{
- rb_lib_log("kq_update_events(): kevent(): %s", strerror(errno));
- return;
+ ret = kevent(kq, kqlst + i, 1, NULL, 0, &zero_timespec);
+ /* jdc -- someone needs to do error checking... */
+ if(ret == -1)
+ {
+ rb_lib_log("kq_update_events(): kevent(): %s", strerror(errno));
+ kqoff = 0;
+ return;
+ }
}
kqoff = 0;
}
}
kqmax = getdtablesize();
kqlst = rb_malloc(sizeof(struct kevent) * kqmax);
+ kqout = rb_malloc(sizeof(struct kevent) * kqmax);
rb_open(kq, RB_FD_UNKNOWN, "kqueue fd");
zero_timespec.tv_sec = 0;
zero_timespec.tv_nsec = 0;
rb_select_kqueue(long delay)
{
int num, i;
- static struct kevent ke[KE_LENGTH];
struct timespec poll_time;
struct timespec *pt;
rb_fde_t *F;
for (;;)
{
- num = kevent(kq, kqlst, kqoff, ke, KE_LENGTH, pt);
+ num = kevent(kq, kqlst, kqoff, kqout, kqmax, pt);
kqoff = 0;
if(num >= 0)
{
PF *hdl = NULL;
- if(ke[i].flags & EV_ERROR)
+ if(kqout[i].flags & EV_ERROR)
{
- errno = ke[i].data;
+ errno = kqout[i].data;
/* XXX error == bad! -- adrian */
continue; /* XXX! */
}
- switch (ke[i].filter)
+ switch (kqout[i].filter)
{
case EVFILT_READ:
- F = ke[i].udata;
+ F = kqout[i].udata;
if((hdl = F->read_handler) != NULL)
{
F->read_handler = NULL;
break;
case EVFILT_WRITE:
- F = ke[i].udata;
+ F = kqout[i].udata;
if((hdl = F->write_handler) != NULL)
{
F->write_handler = NULL;
break;
#if defined(EVFILT_TIMER)
case EVFILT_TIMER:
- rb_run_event(ke[i].udata);
+ rb_run_event(kqout[i].udata);
break;
#endif
default: