6a029ebed745994ce2e5f64182d8b5c8f10d53d6Timo Sirainen/*
6a029ebed745994ce2e5f64182d8b5c8f10d53d6Timo Sirainen * BSD kqueue() based ioloop notify handler.
6a029ebed745994ce2e5f64182d8b5c8f10d53d6Timo Sirainen *
6a029ebed745994ce2e5f64182d8b5c8f10d53d6Timo Sirainen * Copyright (c) 2005 Vaclav Haisman <v.haisman@sh.cvut.cz>
6a029ebed745994ce2e5f64182d8b5c8f10d53d6Timo Sirainen */
6a029ebed745994ce2e5f64182d8b5c8f10d53d6Timo Sirainen
6a029ebed745994ce2e5f64182d8b5c8f10d53d6Timo Sirainen#define _GNU_SOURCE
6a029ebed745994ce2e5f64182d8b5c8f10d53d6Timo Sirainen#include "lib.h"
6a029ebed745994ce2e5f64182d8b5c8f10d53d6Timo Sirainen
6a029ebed745994ce2e5f64182d8b5c8f10d53d6Timo Sirainen#ifdef IOLOOP_NOTIFY_KQUEUE
6a029ebed745994ce2e5f64182d8b5c8f10d53d6Timo Sirainen
0536ccb51d41e3078c3a9fa33e509fb4b2420f95Timo Sirainen#include "ioloop-private.h"
fefe9afdb0fb4cfc70afe3006ec88ba09ab3762dTimo Sirainen#include "llist.h"
6a029ebed745994ce2e5f64182d8b5c8f10d53d6Timo Sirainen#include <unistd.h>
6a029ebed745994ce2e5f64182d8b5c8f10d53d6Timo Sirainen#include <fcntl.h>
6a029ebed745994ce2e5f64182d8b5c8f10d53d6Timo Sirainen#include <sys/types.h>
6a029ebed745994ce2e5f64182d8b5c8f10d53d6Timo Sirainen#include <sys/event.h>
6a029ebed745994ce2e5f64182d8b5c8f10d53d6Timo Sirainen#include <sys/time.h>
a40f21e8239a87a8fab2648955b0f568908ca8b5Timo Sirainen#include <sys/stat.h>
6a029ebed745994ce2e5f64182d8b5c8f10d53d6Timo Sirainen
f6c0407545ee77d4647c8cd912e3156b0a48e2f1Timo Sirainen/* kevent.udata's type just has to be different in NetBSD than in
f6c0407545ee77d4647c8cd912e3156b0a48e2f1Timo Sirainen FreeBSD and OpenBSD.. */
f6c0407545ee77d4647c8cd912e3156b0a48e2f1Timo Sirainen#ifdef __NetBSD__
f6c0407545ee77d4647c8cd912e3156b0a48e2f1Timo Sirainen# define MY_EV_SET(a, b, c, d, e, f, g) \
f6c0407545ee77d4647c8cd912e3156b0a48e2f1Timo Sirainen EV_SET(a, b, c, d, e, f, (intptr_t)g)
f6c0407545ee77d4647c8cd912e3156b0a48e2f1Timo Sirainen#else
f6c0407545ee77d4647c8cd912e3156b0a48e2f1Timo Sirainen# define MY_EV_SET(a, b, c, d, e, f, g) \
f6c0407545ee77d4647c8cd912e3156b0a48e2f1Timo Sirainen EV_SET(a, b, c, d, e, f, g)
f6c0407545ee77d4647c8cd912e3156b0a48e2f1Timo Sirainen#endif
f6c0407545ee77d4647c8cd912e3156b0a48e2f1Timo Sirainen
dcc76bb1e1bb287e3e71e6a39a7ca207fab0eaa8Timo Sirainenstruct io_notify {
dcc76bb1e1bb287e3e71e6a39a7ca207fab0eaa8Timo Sirainen struct io io;
dcc76bb1e1bb287e3e71e6a39a7ca207fab0eaa8Timo Sirainen int refcount;
dcc76bb1e1bb287e3e71e6a39a7ca207fab0eaa8Timo Sirainen int fd;
fefe9afdb0fb4cfc70afe3006ec88ba09ab3762dTimo Sirainen struct io_notify *prev, *next;
dcc76bb1e1bb287e3e71e6a39a7ca207fab0eaa8Timo Sirainen};
dcc76bb1e1bb287e3e71e6a39a7ca207fab0eaa8Timo Sirainen
6a029ebed745994ce2e5f64182d8b5c8f10d53d6Timo Sirainenstruct ioloop_notify_handler_context {
6a029ebed745994ce2e5f64182d8b5c8f10d53d6Timo Sirainen int kq;
6a029ebed745994ce2e5f64182d8b5c8f10d53d6Timo Sirainen struct io *event_io;
fefe9afdb0fb4cfc70afe3006ec88ba09ab3762dTimo Sirainen struct io_notify *notifies;
6a029ebed745994ce2e5f64182d8b5c8f10d53d6Timo Sirainen};
6a029ebed745994ce2e5f64182d8b5c8f10d53d6Timo Sirainen
fefe9afdb0fb4cfc70afe3006ec88ba09ab3762dTimo Sirainenstatic void
fefe9afdb0fb4cfc70afe3006ec88ba09ab3762dTimo Sirainenio_loop_notify_free(struct ioloop_notify_handler_context *ctx,
fefe9afdb0fb4cfc70afe3006ec88ba09ab3762dTimo Sirainen struct io_notify *io)
fefe9afdb0fb4cfc70afe3006ec88ba09ab3762dTimo Sirainen{
fefe9afdb0fb4cfc70afe3006ec88ba09ab3762dTimo Sirainen DLLIST_REMOVE(&ctx->notifies, io);
fefe9afdb0fb4cfc70afe3006ec88ba09ab3762dTimo Sirainen i_free(io);
fefe9afdb0fb4cfc70afe3006ec88ba09ab3762dTimo Sirainen}
fefe9afdb0fb4cfc70afe3006ec88ba09ab3762dTimo Sirainen
2cfe9983ce7a6280636ee12beccc2e865111967bTimo Sirainenstatic void event_callback(struct ioloop_notify_handler_context *ctx)
6a029ebed745994ce2e5f64182d8b5c8f10d53d6Timo Sirainen{
dcc76bb1e1bb287e3e71e6a39a7ca207fab0eaa8Timo Sirainen struct io_notify *io;
dcc76bb1e1bb287e3e71e6a39a7ca207fab0eaa8Timo Sirainen struct kevent events[64];
35565557e05721a761132cec2ba1d93acacb6c14Timo Sirainen struct timespec ts;
dcc76bb1e1bb287e3e71e6a39a7ca207fab0eaa8Timo Sirainen int i, ret;
6a029ebed745994ce2e5f64182d8b5c8f10d53d6Timo Sirainen
35565557e05721a761132cec2ba1d93acacb6c14Timo Sirainen ts.tv_sec = 0;
35565557e05721a761132cec2ba1d93acacb6c14Timo Sirainen ts.tv_nsec = 0;
35565557e05721a761132cec2ba1d93acacb6c14Timo Sirainen
fd1f0e9ef52b3e157cfd1a01c464c2ac7458ab17Timo Sirainen ret = kevent(ctx->kq, NULL, 0, events, N_ELEMENTS(events), &ts);
35565557e05721a761132cec2ba1d93acacb6c14Timo Sirainen if (ret <= 0) {
35565557e05721a761132cec2ba1d93acacb6c14Timo Sirainen if (ret == 0 || errno == EINTR)
35565557e05721a761132cec2ba1d93acacb6c14Timo Sirainen return;
35565557e05721a761132cec2ba1d93acacb6c14Timo Sirainen
35565557e05721a761132cec2ba1d93acacb6c14Timo Sirainen i_fatal("kevent(notify) failed: %m");
35565557e05721a761132cec2ba1d93acacb6c14Timo Sirainen }
dcc76bb1e1bb287e3e71e6a39a7ca207fab0eaa8Timo Sirainen
306f6bb8791755257c0db900f17659402c660057Timo Sirainen if (gettimeofday(&ioloop_timeval, NULL) < 0)
dcc76bb1e1bb287e3e71e6a39a7ca207fab0eaa8Timo Sirainen i_fatal("gettimeofday() failed: %m");
dcc76bb1e1bb287e3e71e6a39a7ca207fab0eaa8Timo Sirainen ioloop_time = ioloop_timeval.tv_sec;
dcc76bb1e1bb287e3e71e6a39a7ca207fab0eaa8Timo Sirainen
dcc76bb1e1bb287e3e71e6a39a7ca207fab0eaa8Timo Sirainen for (i = 0; i < ret; i++) {
dcc76bb1e1bb287e3e71e6a39a7ca207fab0eaa8Timo Sirainen io = (void *)events[i].udata;
6a7bc57cdd2aaa7778478bf76c20c61640c725e6Timo Sirainen i_assert(io->refcount >= 1);
dcc76bb1e1bb287e3e71e6a39a7ca207fab0eaa8Timo Sirainen io->refcount++;
dcc76bb1e1bb287e3e71e6a39a7ca207fab0eaa8Timo Sirainen }
dcc76bb1e1bb287e3e71e6a39a7ca207fab0eaa8Timo Sirainen for (i = 0; i < ret; i++) {
dcc76bb1e1bb287e3e71e6a39a7ca207fab0eaa8Timo Sirainen io = (void *)events[i].udata;
dcc76bb1e1bb287e3e71e6a39a7ca207fab0eaa8Timo Sirainen /* there can be multiple events for a single io.
dcc76bb1e1bb287e3e71e6a39a7ca207fab0eaa8Timo Sirainen call the callback only once if that happens. */
dcc76bb1e1bb287e3e71e6a39a7ca207fab0eaa8Timo Sirainen if (io->refcount == 2 && io->io.callback != NULL)
1388b590dbd85245b591346f860bc1319953318aTimo Sirainen io_loop_call_io(&io->io);
dcc76bb1e1bb287e3e71e6a39a7ca207fab0eaa8Timo Sirainen
dcc76bb1e1bb287e3e71e6a39a7ca207fab0eaa8Timo Sirainen if (--io->refcount == 0)
fefe9afdb0fb4cfc70afe3006ec88ba09ab3762dTimo Sirainen io_loop_notify_free(ctx, io);
dcc76bb1e1bb287e3e71e6a39a7ca207fab0eaa8Timo Sirainen }
6a029ebed745994ce2e5f64182d8b5c8f10d53d6Timo Sirainen}
6a029ebed745994ce2e5f64182d8b5c8f10d53d6Timo Sirainen
dcc76bb1e1bb287e3e71e6a39a7ca207fab0eaa8Timo Sirainenstatic struct ioloop_notify_handler_context *io_loop_notify_handler_init(void)
6a029ebed745994ce2e5f64182d8b5c8f10d53d6Timo Sirainen{
6a029ebed745994ce2e5f64182d8b5c8f10d53d6Timo Sirainen struct ioloop_notify_handler_context *ctx;
6a029ebed745994ce2e5f64182d8b5c8f10d53d6Timo Sirainen
dcc76bb1e1bb287e3e71e6a39a7ca207fab0eaa8Timo Sirainen ctx = current_ioloop->notify_handler_context =
dcc76bb1e1bb287e3e71e6a39a7ca207fab0eaa8Timo Sirainen i_new(struct ioloop_notify_handler_context, 1);
6a029ebed745994ce2e5f64182d8b5c8f10d53d6Timo Sirainen ctx->kq = kqueue();
6a029ebed745994ce2e5f64182d8b5c8f10d53d6Timo Sirainen if (ctx->kq < 0)
35565557e05721a761132cec2ba1d93acacb6c14Timo Sirainen i_fatal("kqueue(notify) failed: %m");
a40f21e8239a87a8fab2648955b0f568908ca8b5Timo Sirainen fd_close_on_exec(ctx->kq, TRUE);
dcc76bb1e1bb287e3e71e6a39a7ca207fab0eaa8Timo Sirainen return ctx;
6a029ebed745994ce2e5f64182d8b5c8f10d53d6Timo Sirainen}
6a029ebed745994ce2e5f64182d8b5c8f10d53d6Timo Sirainen
6a029ebed745994ce2e5f64182d8b5c8f10d53d6Timo Sirainenvoid io_loop_notify_handler_deinit(struct ioloop *ioloop)
6a029ebed745994ce2e5f64182d8b5c8f10d53d6Timo Sirainen{
6a029ebed745994ce2e5f64182d8b5c8f10d53d6Timo Sirainen struct ioloop_notify_handler_context *ctx =
6a029ebed745994ce2e5f64182d8b5c8f10d53d6Timo Sirainen ioloop->notify_handler_context;
6a029ebed745994ce2e5f64182d8b5c8f10d53d6Timo Sirainen
fefe9afdb0fb4cfc70afe3006ec88ba09ab3762dTimo Sirainen while (ctx->notifies != NULL) {
fefe9afdb0fb4cfc70afe3006ec88ba09ab3762dTimo Sirainen struct io_notify *io = ctx->notifies;
fefe9afdb0fb4cfc70afe3006ec88ba09ab3762dTimo Sirainen struct io *_io = &io->io;
fefe9afdb0fb4cfc70afe3006ec88ba09ab3762dTimo Sirainen
dfa23b2ddc43f323112225facf7cd7191e62e02cAki Tuomi i_warning("I/O notify leak: %p (%s:%u, fd %d)",
fefe9afdb0fb4cfc70afe3006ec88ba09ab3762dTimo Sirainen (void *)_io->callback,
dfa23b2ddc43f323112225facf7cd7191e62e02cAki Tuomi _io->source_filename,
fefe9afdb0fb4cfc70afe3006ec88ba09ab3762dTimo Sirainen _io->source_linenum, io->fd);
fefe9afdb0fb4cfc70afe3006ec88ba09ab3762dTimo Sirainen io_remove(&_io);
fefe9afdb0fb4cfc70afe3006ec88ba09ab3762dTimo Sirainen }
fefe9afdb0fb4cfc70afe3006ec88ba09ab3762dTimo Sirainen
5f1d689131a75c39f064cbd4202373e7edf78f18Josef 'Jeff' Sipek io_remove(&ctx->event_io);
6a029ebed745994ce2e5f64182d8b5c8f10d53d6Timo Sirainen if (close(ctx->kq) < 0)
6a029ebed745994ce2e5f64182d8b5c8f10d53d6Timo Sirainen i_error("close(kqueue notify) failed: %m");
dcc76bb1e1bb287e3e71e6a39a7ca207fab0eaa8Timo Sirainen i_free(ctx);
6a029ebed745994ce2e5f64182d8b5c8f10d53d6Timo Sirainen}
6a029ebed745994ce2e5f64182d8b5c8f10d53d6Timo Sirainen
dcc76bb1e1bb287e3e71e6a39a7ca207fab0eaa8Timo Sirainen#undef io_add_notify
f6845101f2d6b8068e352a0b5a0d4bb04e20ad74Timo Sirainenenum io_notify_result
dfa23b2ddc43f323112225facf7cd7191e62e02cAki Tuomiio_add_notify(const char *path, const char *source_filename,
dfa23b2ddc43f323112225facf7cd7191e62e02cAki Tuomi unsigned int source_linenum,
f6845101f2d6b8068e352a0b5a0d4bb04e20ad74Timo Sirainen io_callback_t *callback, void *context, struct io **io_r)
6a029ebed745994ce2e5f64182d8b5c8f10d53d6Timo Sirainen{
6a029ebed745994ce2e5f64182d8b5c8f10d53d6Timo Sirainen struct ioloop_notify_handler_context *ctx =
dcc76bb1e1bb287e3e71e6a39a7ca207fab0eaa8Timo Sirainen current_ioloop->notify_handler_context;
35565557e05721a761132cec2ba1d93acacb6c14Timo Sirainen struct kevent ev;
dcc76bb1e1bb287e3e71e6a39a7ca207fab0eaa8Timo Sirainen struct io_notify *io;
6a029ebed745994ce2e5f64182d8b5c8f10d53d6Timo Sirainen int fd;
a40f21e8239a87a8fab2648955b0f568908ca8b5Timo Sirainen
dcc76bb1e1bb287e3e71e6a39a7ca207fab0eaa8Timo Sirainen if (ctx == NULL)
dcc76bb1e1bb287e3e71e6a39a7ca207fab0eaa8Timo Sirainen ctx = io_loop_notify_handler_init();
dcc76bb1e1bb287e3e71e6a39a7ca207fab0eaa8Timo Sirainen
6a029ebed745994ce2e5f64182d8b5c8f10d53d6Timo Sirainen fd = open(path, O_RDONLY);
6a029ebed745994ce2e5f64182d8b5c8f10d53d6Timo Sirainen if (fd == -1) {
5c6410e8882d021ad9cff91d87b3ce68e309bd44Timo Sirainen /* ESTALE could happen with NFS. Don't bother giving an error
5c6410e8882d021ad9cff91d87b3ce68e309bd44Timo Sirainen message then. */
5c6410e8882d021ad9cff91d87b3ce68e309bd44Timo Sirainen if (errno != ENOENT && errno != ESTALE)
35565557e05721a761132cec2ba1d93acacb6c14Timo Sirainen i_error("open(%s) for kq notify failed: %m", path);
1964dbea138cb4a213b1bce1eeee68992b18829aTimo Sirainen return IO_NOTIFY_NOTFOUND;
6a029ebed745994ce2e5f64182d8b5c8f10d53d6Timo Sirainen }
a40f21e8239a87a8fab2648955b0f568908ca8b5Timo Sirainen fd_close_on_exec(fd, TRUE);
6a029ebed745994ce2e5f64182d8b5c8f10d53d6Timo Sirainen
dcc76bb1e1bb287e3e71e6a39a7ca207fab0eaa8Timo Sirainen io = i_new(struct io_notify, 1);
ec096c8a0f52a4bb5d12aa9afe1a576368aa8094Timo Sirainen io->io.condition = IO_NOTIFY;
5535f5fb5feef602cc21678aa2db11a2809e8f76Timo Sirainen io->io.source_filename = source_filename;
f6845101f2d6b8068e352a0b5a0d4bb04e20ad74Timo Sirainen io->io.source_linenum = source_linenum;
dcc76bb1e1bb287e3e71e6a39a7ca207fab0eaa8Timo Sirainen io->io.callback = callback;
dcc76bb1e1bb287e3e71e6a39a7ca207fab0eaa8Timo Sirainen io->io.context = context;
193f5296d2a6b847970c222d8a261b89aae46331Timo Sirainen io->io.ioloop = current_ioloop;
dcc76bb1e1bb287e3e71e6a39a7ca207fab0eaa8Timo Sirainen io->refcount = 1;
6a029ebed745994ce2e5f64182d8b5c8f10d53d6Timo Sirainen io->fd = fd;
35565557e05721a761132cec2ba1d93acacb6c14Timo Sirainen
4dc5662260a63669054cd0dc1bac2ccab3fa2ae7Timo Sirainen /* EV_CLEAR flag is needed because the EVFILT_VNODE filter reports
4dc5662260a63669054cd0dc1bac2ccab3fa2ae7Timo Sirainen event state transitions and not the current state. With this flag,
4dc5662260a63669054cd0dc1bac2ccab3fa2ae7Timo Sirainen the same event is only returned once. */
f6c0407545ee77d4647c8cd912e3156b0a48e2f1Timo Sirainen MY_EV_SET(&ev, fd, EVFILT_VNODE, EV_ADD | EV_CLEAR,
f3739947c8a5f8584fe630ec138058c5bd53184fTimo Sirainen NOTE_DELETE | NOTE_RENAME | NOTE_WRITE | NOTE_EXTEND |
f3739947c8a5f8584fe630ec138058c5bd53184fTimo Sirainen NOTE_REVOKE, 0, io);
a40f21e8239a87a8fab2648955b0f568908ca8b5Timo Sirainen if (kevent(ctx->kq, &ev, 1, NULL, 0, NULL) < 0) {
a40f21e8239a87a8fab2648955b0f568908ca8b5Timo Sirainen i_error("kevent(%d, %s) for notify failed: %m", fd, path);
4307c886579381dbb1897ea1388ae6978c96f560Timo Sirainen i_close_fd(&fd);
dcc76bb1e1bb287e3e71e6a39a7ca207fab0eaa8Timo Sirainen i_free(io);
0a3d3ca7db7cbdc947ccabe740c40561b3f5c066Timo Sirainen return IO_NOTIFY_NOSUPPORT;
a40f21e8239a87a8fab2648955b0f568908ca8b5Timo Sirainen }
6a029ebed745994ce2e5f64182d8b5c8f10d53d6Timo Sirainen
6a029ebed745994ce2e5f64182d8b5c8f10d53d6Timo Sirainen if (ctx->event_io == NULL) {
dcc76bb1e1bb287e3e71e6a39a7ca207fab0eaa8Timo Sirainen ctx->event_io = io_add(ctx->kq, IO_READ, event_callback,
193f5296d2a6b847970c222d8a261b89aae46331Timo Sirainen io->io.ioloop->notify_handler_context);
6a029ebed745994ce2e5f64182d8b5c8f10d53d6Timo Sirainen }
fefe9afdb0fb4cfc70afe3006ec88ba09ab3762dTimo Sirainen DLLIST_PREPEND(&ctx->notifies, io);
1964dbea138cb4a213b1bce1eeee68992b18829aTimo Sirainen *io_r = &io->io;
1964dbea138cb4a213b1bce1eeee68992b18829aTimo Sirainen return IO_NOTIFY_ADDED;
6a029ebed745994ce2e5f64182d8b5c8f10d53d6Timo Sirainen}
6a029ebed745994ce2e5f64182d8b5c8f10d53d6Timo Sirainen
193f5296d2a6b847970c222d8a261b89aae46331Timo Sirainenvoid io_loop_notify_remove(struct io *_io)
6a029ebed745994ce2e5f64182d8b5c8f10d53d6Timo Sirainen{
6a029ebed745994ce2e5f64182d8b5c8f10d53d6Timo Sirainen struct ioloop_notify_handler_context *ctx =
193f5296d2a6b847970c222d8a261b89aae46331Timo Sirainen _io->ioloop->notify_handler_context;
dcc76bb1e1bb287e3e71e6a39a7ca207fab0eaa8Timo Sirainen struct io_notify *io = (struct io_notify *)_io;
35565557e05721a761132cec2ba1d93acacb6c14Timo Sirainen struct kevent ev;
a40f21e8239a87a8fab2648955b0f568908ca8b5Timo Sirainen
f6c0407545ee77d4647c8cd912e3156b0a48e2f1Timo Sirainen MY_EV_SET(&ev, io->fd, EVFILT_VNODE, EV_DELETE, 0, 0, NULL);
a40f21e8239a87a8fab2648955b0f568908ca8b5Timo Sirainen if (kevent(ctx->kq, &ev, 1, NULL, 0, 0) < 0)
a40f21e8239a87a8fab2648955b0f568908ca8b5Timo Sirainen i_error("kevent(%d) for notify remove failed: %m", io->fd);
a40f21e8239a87a8fab2648955b0f568908ca8b5Timo Sirainen if (close(io->fd) < 0)
35565557e05721a761132cec2ba1d93acacb6c14Timo Sirainen i_error("close(%d) for notify remove failed: %m", io->fd);
dcc76bb1e1bb287e3e71e6a39a7ca207fab0eaa8Timo Sirainen io->fd = -1;
dcc76bb1e1bb287e3e71e6a39a7ca207fab0eaa8Timo Sirainen
dcc76bb1e1bb287e3e71e6a39a7ca207fab0eaa8Timo Sirainen if (--io->refcount == 0)
fefe9afdb0fb4cfc70afe3006ec88ba09ab3762dTimo Sirainen io_loop_notify_free(ctx, io);
6a029ebed745994ce2e5f64182d8b5c8f10d53d6Timo Sirainen}
6a029ebed745994ce2e5f64182d8b5c8f10d53d6Timo Sirainen
dad206f8341603837b7de4309a7c195da26cf9aaTimo Sirainenint io_loop_extract_notify_fd(struct ioloop *ioloop)
dad206f8341603837b7de4309a7c195da26cf9aaTimo Sirainen{
dad206f8341603837b7de4309a7c195da26cf9aaTimo Sirainen struct ioloop_notify_handler_context *ctx =
dad206f8341603837b7de4309a7c195da26cf9aaTimo Sirainen ioloop->notify_handler_context;
dad206f8341603837b7de4309a7c195da26cf9aaTimo Sirainen struct io_notify *io;
dad206f8341603837b7de4309a7c195da26cf9aaTimo Sirainen int fd, new_kq;
dad206f8341603837b7de4309a7c195da26cf9aaTimo Sirainen
a6280be05b9c90579bb59ff57a3035661706c3d3Timo Sirainen if (ctx == NULL || ctx->kq == -1)
dad206f8341603837b7de4309a7c195da26cf9aaTimo Sirainen return -1;
dad206f8341603837b7de4309a7c195da26cf9aaTimo Sirainen
a350c75b6e22e6e8f246964924d9a4715d16af08Timo Sirainen new_kq = kqueue();
a350c75b6e22e6e8f246964924d9a4715d16af08Timo Sirainen if (new_kq < 0) {
a350c75b6e22e6e8f246964924d9a4715d16af08Timo Sirainen i_error("kqueue(notify) failed: %m");
dad206f8341603837b7de4309a7c195da26cf9aaTimo Sirainen return -1;
dad206f8341603837b7de4309a7c195da26cf9aaTimo Sirainen }
a350c75b6e22e6e8f246964924d9a4715d16af08Timo Sirainen for (io = ctx->notifies; io != NULL; io = io->next)
dad206f8341603837b7de4309a7c195da26cf9aaTimo Sirainen io->fd = -1;
5f1d689131a75c39f064cbd4202373e7edf78f18Josef 'Jeff' Sipek io_remove(&ctx->event_io);
dad206f8341603837b7de4309a7c195da26cf9aaTimo Sirainen fd = ctx->kq;
dad206f8341603837b7de4309a7c195da26cf9aaTimo Sirainen ctx->kq = new_kq;
dad206f8341603837b7de4309a7c195da26cf9aaTimo Sirainen return fd;
dad206f8341603837b7de4309a7c195da26cf9aaTimo Sirainen}
dad206f8341603837b7de4309a7c195da26cf9aaTimo Sirainen
6a029ebed745994ce2e5f64182d8b5c8f10d53d6Timo Sirainen#endif