summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2007-07-10 22:41:39 +0000
committerLennart Poettering <lennart@poettering.net>2007-07-10 22:41:39 +0000
commit9225e01a984f730e6b2755a37e83c7ca4ee601cb (patch)
tree3f7639f44a5664b6f64707ee2132df3b2bcd195c
parenta2243229bc2fb20b0c010b3830f79ef2d2383ccd (diff)
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
-rw-r--r--avahi-daemon/main.c110
-rw-r--r--configure.ac9
2 files changed, 119 insertions, 0 deletions
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 <sys/types.h>
+#include <sys/event.h>
+#include <unistd.h>
+#endif
+
#include <libdaemon/dfork.h>
#include <libdaemon/dsignal.h>
#include <libdaemon/dlog.h>
@@ -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)