From 9225e01a984f730e6b2755a37e83c7ca4ee601cb Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 10 Jul 2007 22:41:39 +0000 Subject: Add FreeBSD kqueue support for watching for configuration file changes, much the same way we currently have for Linux with inotify. (Patch supplied by marcus, but autoconf check reversed, re #149) git-svn-id: file:///home/lennart/svn/public/avahi/trunk@1495 941a03a8-eaeb-0310-b9a0-b1bbd8fe43fe --- avahi-daemon/main.c | 110 ++++++++++++++++++++++++++++++++++++++++++++++++++++ configure.ac | 9 +++++ 2 files changed, 119 insertions(+) diff --git a/avahi-daemon/main.c b/avahi-daemon/main.c index 884ad2e..460a9d6 100644 --- a/avahi-daemon/main.c +++ b/avahi-daemon/main.c @@ -50,6 +50,12 @@ #endif #endif +#ifdef HAVE_KQUEUE +#include +#include +#include +#endif + #include #include #include @@ -691,6 +697,53 @@ static void add_inotify_watches(void) { #endif +#ifdef HAVE_KQUEUE + +#define NUM_WATCHES 2 + +static int kq = -1; +static int kfds[NUM_WATCHES]; +static int num_kfds = 0; + +static void add_kqueue_watch(const char *dir); + +static void add_kqueue_watches(void) { + int c = 0; + +#ifdef ENABLE_CHROOT + c = config.use_chroot; +#endif + + add_kqueue_watch(c ? "/" : AVAHI_CONFIG_DIR); + add_kqueue_watch(c ? "/services" : AVAHI_SERVICE_DIR); +} + +static void add_kqueue_watch(const char *dir) { + int fd; + struct kevent ev; + + if (kq < 0) + return; + + if (num_kfds >= NUM_WATCHES) + return; + + fd = open(dir, O_RDONLY); + if (fd < 0) + return; + EV_SET(&ev, fd, EVFILT_VNODE, EV_ADD | EV_ENABLE | EV_CLEAR, + NOTE_DELETE | NOTE_EXTEND | NOTE_WRITE | NOTE_RENAME, + 0, 0); + if (kevent(kq, &ev, 1, NULL, 0, NULL) == -1) { + close(fd); + return; + } + + kfds[num_kfds++] = fd; +} + +#endif + static void reload_config(void) { #ifdef HAVE_INOTIFY @@ -698,6 +751,10 @@ static void reload_config(void) { add_inotify_watches(); #endif +#ifdef HAVE_KQUEUE + add_kqueue_watches(); +#endif + #ifdef ENABLE_CHROOT static_service_load(config.use_chroot); static_hosts_load(config.use_chroot); @@ -746,6 +803,31 @@ static void inotify_callback(AvahiWatch *watch, int fd, AVAHI_GCC_UNUSED AvahiWa #endif +#ifdef HAVE_KQUEUE + +static void kqueue_callback(AvahiWatch *watch, int fd, AVAHI_GCC_UNUSED AvahiWatchEvent event, AVAHI_GCC_UNUSED void *userdata) { + struct kevent ev; + struct timespec nullts = { 0, 0 }; + int res; + + assert(fd == kq); + assert(watch); + + res = kevent(kq, NULL, 0, &ev, 1, &nullts); + + if (res > 0) { + /* Sleep for a half-second to avoid potential races + * during install/uninstall. */ + usleep(500000); + avahi_log_info("Files changed, reloading."); + reload_config(); + } else { + avahi_log_error("Failed to read kqueue event: %s", avahi_strerror(errno)); + } +} + +#endif + static void signal_callback(AvahiWatch *watch, AVAHI_GCC_UNUSED int fd, AVAHI_GCC_UNUSED AvahiWatchEvent event, AVAHI_GCC_UNUSED void *userdata) { int sig; const AvahiPoll *poll_api; @@ -801,6 +883,10 @@ static int run_server(DaemonConfig *c) { #ifdef HAVE_INOTIFY AvahiWatch *inotify_watch = NULL; #endif +#ifdef HAVE_KQUEUE + int i; + AvahiWatch *kqueue_watch = NULL; +#endif assert(c); @@ -876,6 +962,19 @@ static int run_server(DaemonConfig *c) { } #endif +#ifdef HAVE_KQUEUE + if ((kq = kqueue()) < 0) + avahi_log_warn( "Failed to initialize kqueue: %s", strerror(errno)); + else { + add_kqueue_watches(); + + if (!(kqueue_watch = poll_api->watch_new(poll_api, kq, AVAHI_WATCH_IN, kqueue_callback, NULL))) { + avahi_log_error( "Failed to create kqueue watcher"); + goto finish; + } + } +#endif + load_resolv_conf(); #ifdef ENABLE_CHROOT static_service_load(config.use_chroot); @@ -945,6 +1044,17 @@ finish: if (inotify_fd >= 0) close(inotify_fd); #endif + +#ifdef HAVE_KQUEUE + if (kqueue_watch) + poll_api->watch_free(kqueue_watch); + if (kq >= 0) + close(kq); + for (i = 0; i < num_kfds; i++) { + if (kfds[i] >= 0) + close(kfds[i]); + } +#endif if (simple_poll_api) { avahi_simple_poll_free(simple_poll_api); diff --git a/configure.ac b/configure.ac index 8352d1b..0c205c0 100644 --- a/configure.ac +++ b/configure.ac @@ -384,6 +384,15 @@ if test "x$have_inotify" = "xyes" ; then AC_DEFINE([HAVE_INOTIFY], 1, [Enable Linux inotify() usage]) fi +have_kqueue=yes +AC_CHECK_FUNCS([kqueue],,have_kqueue=no) + +AM_CONDITIONAL(HAVE_KQUEUE, test "x$have_kqueue" = "xyes") + +if test "x$have_kqueue" = "xyes" ; then + AC_DEFINE([HAVE_KQUEUE], 1, [Enable BSD kqueue() usage]) +fi + # Check for pkg-config manually first, as if its not installed the # PKG_PROG_PKG_CONFIG macro won't be defined. AC_CHECK_PROG(have_pkg_config, pkg-config, yes, no) -- cgit