140 lines
3.7 KiB
Plaintext
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
|