Václav Haisman wrote:
The attached patch should fix the problem with dying imap on "Unrecognized event". The problem is that when we register a handle for IO_ERROR only, we still can get readable/writable event without EV_EOF being set. This case was not handled.
-- Vaclav Haisman The fix uncovered another related glitch. If we are waiting just on IO_ERROR then we get readable/writable event all the time, because kqueue is level triggered by default and the codition is always present, and the result is busy loop. Adding EV_CLEAR bit in this case should fix it.
-- Vaclav Haisman
*** ioloop-kqueue.c.~1.4.~ Tue May 2 14:36:56 2006 --- ioloop-kqueue.c Wed May 10 11:23:02 2006
*** 74,80 **** { struct ioloop_handler_context *ctx = ioloop->handler_context; const int fd = io->fd; ! struct kevent ev = { fd, 0, EV_ADD | EV_EOF, 0, 0, NULL }; enum io_condition condition = io->condition & MASK;
i_assert(io->callback != NULL);
--- 74,80 ---- { struct ioloop_handler_context *ctx = ioloop->handler_context; const int fd = io->fd; ! struct kevent ev = { fd, 0, EV_ADD, 0, 0, NULL }; enum io_condition condition = io->condition & MASK;
i_assert(io->callback != NULL);
*** 101,106 **** --- 101,108 ---- if (condition & (IO_READ | IO_ERROR)) { ctx->fds[fd].mode |= condition; ev.filter = EVFILT_READ;
if ((condition & IO_ERROR) == IO_ERROR)
if (kevent(ctx->kq, &ev, 1, NULL, 0, NULL) < 0) { i_error("kevent(%d) in io_loop_handle_add() failed: %m", fd);
*** 109,114 **** --- 111,118 ---- if (condition & (IO_WRITE | IO_ERROR)) { ctx->fds[fd].mode |= condition; ev.filter = EVFILT_WRITE;
if ((condition & IO_ERROR) == IO_ERROR)
if (kevent(ctx->kq, &ev, 1, NULL, 0, NULL) < 0) { i_error("kevent(%d) in io_loop_handle_add() failed: %m", fd);
*** 184,190 ****
i_assert(ctx->evbuf[i].ident < ctx->fds_size);
if ((ctx->fds[ctx->evbuf[i].ident].mode & IO_ERROR) &&
! (ctx->evbuf[i].flags & EV_EOF)) { struct io *errio = ctx->fds[ctx->evbuf[i].ident].errio;
t_id = t_push();
--- 188,194 ----
i_assert(ctx->evbuf[i].ident < ctx->fds_size);
if ((ctx->fds[ctx->evbuf[i].ident].mode & IO_ERROR) &&
! (ctx->evbuf[i].flags & (EV_EOF | EV_ERROR))) { struct io *errio = ctx->fds[ctx->evbuf[i].ident].errio;
t_id = t_push();
*** 203,216 **** " in I/O handler %p", (void *)io->callback); } } else i_panic("Unrecognized event: kevent {.ident = %u," " .filter = 0x%04x," " .flags = 0x%04x," " .fflags = 0x%08x," ! " .data = 0x%08x}", ctx->evbuf[i].ident, ctx->evbuf[i].filter, ctx->evbuf[i].flags, ! ctx->evbuf[i].fflags, ctx->evbuf[i].data); } }
--- 207,228 ---- " in I/O handler %p", (void *)io->callback); }
} else if (ctx->fds[ctx->evbuf[i].ident].mode & IO_ERROR) {
! " .data = 0x%08x}\n" ! "mode: 0x%x04x", ctx->evbuf[i].ident, ctx->evbuf[i].filter, ctx->evbuf[i].flags, ! ctx->evbuf[i].fflags, ctx->evbuf[i].data, ! ctx->fds[ctx->evbuf[i].ident].mode); } }} else i_panic("Unrecognized event: kevent {.ident = %u," " .filter = 0x%04x," " .flags = 0x%04x," " .fflags = 0x%08x,"