From: Lennart Poettering Date: Tue, 10 Jul 2007 22:41:39 +0000 (+0000) Subject: Add FreeBSD kqueue support for watching for configuration file changes, much the... X-Git-Url: http://git.meshlink.io/?p=catta;a=commitdiff_plain;h=9225e01a984f730e6b2755a37e83c7ca4ee601cb 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 --- 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)