Mercurial > dovecot > original-hg > dovecot-1.2
view src/lib/ioloop-notify-dn.c @ 3649:8c63af0ab91a HEAD
Fixed some printf-type mismatches
author | Timo Sirainen <tss@iki.fi> |
---|---|
date | Wed, 12 Oct 2005 20:14:21 +0300 |
parents | 377f69be914f |
children | 4fa8e287486e |
line wrap: on
line source
/* Copyright (C) 2003 Timo Sirainen */ /* Logic is pretty much based on dnotify by Oskar Liljeblad. */ #define _GNU_SOURCE #include "lib.h" #ifdef IOLOOP_NOTIFY_DNOTIFY #include "ioloop-internal.h" #include "fd-set-nonblock.h" #include "fd-close-on-exec.h" #include <signal.h> #include <unistd.h> #include <fcntl.h> struct ioloop_notify_handler_context { struct io *event_io; int disabled; }; static int event_pipe[2] = { -1, -1 }; static void sigrt_handler(int signo __attr_unused__, siginfo_t *si, void *data __attr_unused__) { int ret; ret = write(event_pipe[1], &si->si_fd, sizeof(int)); if (ret < 0 && errno != EINTR && errno != EAGAIN) i_fatal("write(event_pipe) failed: %m"); i_assert(ret <= 0 || ret == sizeof(int)); } static void event_callback(void *context) { struct ioloop *ioloop = context; struct io *io; int fd, ret; ret = read(event_pipe[0], &fd, sizeof(fd)); if (ret < 0) i_fatal("read(event_pipe) failed: %m"); if (ret != sizeof(fd)) { i_fatal("read(event_pipe) returned %d != %"PRIuSIZE_T, ret, sizeof(fd)); } if (gettimeofday(&ioloop_timeval, &ioloop_timezone) < 0) i_fatal("gettimeofday(): %m"); ioloop_time = ioloop_timeval.tv_sec; for (io = ioloop->notifys; io != NULL; io = io->next) { if (io->fd == fd) { io->callback(io->context); break; } } } struct io *io_loop_notify_add(struct ioloop *ioloop, const char *path, io_callback_t *callback, void *context) { struct ioloop_notify_handler_context *ctx = ioloop->notify_handler_context; struct io *io; int fd; fd = open(path, O_RDONLY); if (fd == -1) { i_error("open(%s) for dnotify failed: %m", path); return NULL; } if (fcntl(fd, F_SETSIG, SIGRTMIN) < 0) { if (errno == EINVAL) { /* dnotify not in kernel. disable it. */ ctx->disabled = TRUE; } else { i_error("fcntl(F_SETSIG) failed: %m"); } (void)close(fd); return NULL; } if (fcntl(fd, F_NOTIFY, DN_CREATE | DN_DELETE | DN_RENAME | DN_MULTISHOT) < 0) { /* we fail here if we're trying to add dnotify to non-directory fd. fail silently in that case. */ if (errno != ENOTDIR) i_error("fcntl(F_NOTIFY) failed: %m"); (void)fcntl(fd, F_SETSIG, 0); (void)close(fd); return NULL; } if (ctx->event_io == NULL) { ctx->event_io = io_add(event_pipe[0], IO_READ, event_callback, ioloop); } io = p_new(ioloop->pool, struct io, 1); io->fd = fd; io->callback = callback; io->context = context; io->next = ioloop->notifys; ioloop->notifys = io; return io; } void io_loop_notify_remove(struct ioloop *ioloop, struct io *io) { struct ioloop_notify_handler_context *ctx = ioloop->notify_handler_context; struct io **io_p; if (ctx->disabled) return; for (io_p = &ioloop->notifys; *io_p != NULL; io_p = &(*io_p)->next) { if (*io_p == io) { *io_p = io->next; break; } } if (fcntl(io->fd, F_NOTIFY, 0) < 0) i_error("fcntl(F_NOTIFY, 0) failed: %m"); if (fcntl(io->fd, F_SETSIG, 0) < 0) i_error("fcntl(F_SETSIG, 0) failed: %m"); if (close(io->fd)) i_error("close(dnotify) failed: %m"); p_free(ioloop->pool, io); if (ioloop->notifys == NULL) { io_remove(ctx->event_io); ctx->event_io = NULL; } } void io_loop_notify_handler_init(struct ioloop *ioloop) { struct ioloop_notify_handler_context *ctx; struct sigaction act; i_assert(event_pipe[0] == -1); ctx = ioloop->notify_handler_context = i_new(struct ioloop_notify_handler_context, 1); if (pipe(event_pipe) < 0) { i_fatal("pipe() failed: %m"); return; } fd_set_nonblock(event_pipe[0], TRUE); fd_set_nonblock(event_pipe[1], TRUE); fd_close_on_exec(event_pipe[0], TRUE); fd_close_on_exec(event_pipe[1], TRUE); /* SIGIO is sent if queue gets full. we'll just ignore it. */ signal(SIGIO, SIG_IGN); act.sa_sigaction = sigrt_handler; sigemptyset(&act.sa_mask); act.sa_flags = SA_SIGINFO | SA_RESTART | SA_NODEFER; if (sigaction(SIGRTMIN, &act, NULL) < 0) i_fatal("sigaction(SIGRTMIN) failed: %m"); } void io_loop_notify_handler_deinit(struct ioloop *ioloop __attr_unused__) { struct ioloop_notify_handler_context *ctx = ioloop->notify_handler_context; signal(SIGRTMIN, SIG_IGN); if (close(event_pipe[0]) < 0) i_error("close(event_pipe[0]) failed: %m"); if (close(event_pipe[1]) < 0) i_error("close(event_pipe[1]) failed: %m"); i_free(ctx); } #endif