openbsd-ports/mail/dovecot/patches/patch-src_lib_ioloop-notify-kqueue_c
2006-01-23 20:33:40 +00:00

140 lines
3.7 KiB
Plaintext

$OpenBSD: patch-src_lib_ioloop-notify-kqueue_c,v 1.2 2006/01/23 20:33:40 brad Exp $
--- src/lib/ioloop-notify-kqueue.c.orig Sat Jan 14 18:27:11 2006
+++ src/lib/ioloop-notify-kqueue.c Mon Jan 23 15:11:11 2006
@@ -15,11 +15,13 @@
#ifdef IOLOOP_NOTIFY_KQUEUE
#include "ioloop-internal.h"
+#include "fd-close-on-exec.h"
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/event.h>
#include <sys/time.h>
+#include <sys/stat.h>
struct ioloop_notify_handler_context {
int kq;
@@ -53,7 +55,8 @@ void io_loop_notify_handler_init(struct
ctx->event_io = NULL;
ctx->kq = kqueue();
if (ctx->kq < 0)
- i_fatal("kqueue() failed: %m");
+ i_fatal("kqueue() for io_loop_notify_handler_init() failed: %m");
+ fd_close_on_exec(ctx->kq, TRUE);
}
void io_loop_notify_handler_deinit(struct ioloop *ioloop)
@@ -61,8 +64,8 @@ void io_loop_notify_handler_deinit(struc
struct ioloop_notify_handler_context *ctx =
ioloop->notify_handler_context;
- if (ctx->event_io)
- io_remove(ctx->event_io);
+ if (ctx->event_io)
+ io_remove(&ctx->event_io);
if (close(ctx->kq) < 0)
i_error("close(kqueue notify) failed: %m");
p_free(ioloop->pool, ctx);
@@ -75,6 +78,11 @@ static void unchain_io (struct ioloop *i
for (io_p = &ioloop->notifys; *io_p != NULL; io_p = &(*io_p)->next) {
if (*io_p == io) {
*io_p = io->next;
+ if (io->next) {
+ io->next->prev = io->prev;
+ }
+ io->prev = NULL;
+ io->next = NULL;
break;
}
}
@@ -90,25 +98,41 @@ struct io *io_loop_notify_add(struct iol
| NOTE_REVOKE, 0, NULL };
struct io *io;
int fd;
+ struct stat sb;
+ i_assert(callback);
fd = open(path, O_RDONLY);
if (fd == -1) {
i_error("open(%s) for notify failed: %m", path);
return NULL;
}
+ fd_close_on_exec(fd, TRUE);
- ev.ident = fd;
- ev.udata = io;
- if (kevent(ctx->kq, &ev, 1, NULL, 0, NULL) < 0) {
- i_error("kevent(%s) for notify failed: %m", path);
+ if (fstat(fd, &sb) == -1) {
+ i_error("fstat(%d \"%s\") for notify failed: %m", fd, path);
+ close(fd);
return NULL;
}
+ if (! (sb.st_mode & S_IFDIR)) {
+ close(fd);
+ return NULL;
+ }
io = p_new(ioloop->pool, struct io, 1);
io->fd = fd;
io->callback = callback;
io->context = context;
+ ev.ident = fd;
+ ev.udata = io;
+ if (kevent(ctx->kq, &ev, 1, NULL, 0, NULL) < 0) {
+ i_error("kevent(%s) for notify failed: fd:%d, %m", path, fd);
+ p_free(ioloop->pool, io);
+ return NULL;
+ }
io->next = ioloop->notifys;
+ io->prev = NULL;
+ if (ioloop->notifys)
+ ioloop->notifys->prev = io;
ioloop->notifys = io;
if (ctx->event_io == NULL) {
@@ -116,7 +140,6 @@ struct io *io_loop_notify_add(struct iol
io_add(ctx->kq, IO_READ, event_callback,
ioloop->notify_handler_context);
}
-
return io;
}
@@ -124,15 +147,29 @@ void io_loop_notify_remove(struct ioloop
{
struct ioloop_notify_handler_context *ctx =
ioloop->notify_handler_context;
- struct kevent ev = { io->fd, 0, EV_DELETE, 0, 0, NULL };
+ struct kevent ev = { io->fd, EVFILT_VNODE, EV_DELETE, 0, 0, NULL };
+ struct stat sb;
int ret;
+ if (fcntl(io->fd, F_GETFD, 0) != -1 || errno != EBADF) {
+ if (fstat(io->fd, &sb) == -1) {
+ i_error("fstat(%d) for notify_remove failed:"
+ " %m", io->fd);
+ return;
+ }
+ if (! (sb.st_mode & S_IFDIR)) {
+ i_error("calling io_loop_notify_remove on non-dir"
+ " handle");
+ return;
+ }
+ ret = kevent(ctx->kq, &ev, 1, NULL, 0, 0);
+ if (ret == -1)
+ i_error("kevent() for notify remove failed, "
+ "but fd:%d is valid: (%d) %m", io->fd, errno);
+ }
+ close(io->fd);
unchain_io(ioloop, io);
p_free(ioloop->pool, io);
-
- ret = kevent(ctx->kq, &ev, 1, NULL, 0, 0);
- if (ret == -1)
- i_error("kevent() for notify failed: %m");
}
#endif