changeset 7459:63cd8ec2007a HEAD

Better error handling for dnotify failures.
author Timo Sirainen <tss@iki.fi>
date Thu, 24 Apr 2008 17:24:32 +0300
parents 43674a726a92
children e1fe3d080314
files src/lib/ioloop-notify-dn.c
diffstat 1 files changed, 29 insertions(+), 16 deletions(-) [+]
line wrap: on
line diff
--- a/src/lib/ioloop-notify-dn.c	Thu Apr 24 17:03:10 2008 +0300
+++ b/src/lib/ioloop-notify-dn.c	Thu Apr 24 17:24:32 2008 +0300
@@ -29,6 +29,21 @@
 
 static struct ioloop_notify_handler_context *io_loop_notify_handler_init(void);
 
+static void ioloop_dnotify_disable(struct ioloop_notify_handler_context *ctx)
+{
+	if (ctx->disabled)
+		return;
+
+	if (--sigrt_refcount == 0)
+		signal(SIGRTMIN, SIG_IGN);
+
+	if (close(ctx->event_pipe[0]) < 0)
+		i_error("close(dnotify pipe[0]) failed: %m");
+	if (close(ctx->event_pipe[1]) < 0)
+		i_error("close(dnotify pipe[1]) failed: %m");
+	ctx->disabled = TRUE;
+}
+
 static void sigrt_handler(int signo ATTR_UNUSED, siginfo_t *si,
 			  void *data ATTR_UNUSED)
 {
@@ -37,9 +52,14 @@
 	int saved_errno = errno;
 	int ret;
 
+	if (ctx->disabled)
+		return;
+
 	ret = write(ctx->event_pipe[1], &si->si_fd, sizeof(int));
-	if (ret < 0 && errno != EINTR && errno != EAGAIN)
-		i_fatal("write(event_pipe) failed: %m");
+	if (ret < 0 && errno != EINTR && errno != EAGAIN) {
+		i_error("write(dnotify pipe) failed: %m");
+		ioloop_dnotify_disable(ctx);
+	}
 
 	i_assert(ret <= 0 || ret == sizeof(int));
 
@@ -55,9 +75,9 @@
 
 	ret = read(ctx->event_pipe[0], fd_buf, sizeof(fd_buf));
 	if (ret < 0)
-		i_fatal("read(event_pipe) failed: %m");
+		i_fatal("read(dnotify pipe) failed: %m");
 	if ((ret % sizeof(fd_buf[0])) != 0)
-		i_fatal("read(event_pipe) returned %d", ret);
+		i_fatal("read(dnotify pipe) returned %d", ret);
 	ret /= sizeof(fd_buf[0]);
 
 	if (gettimeofday(&ioloop_timeval, &ioloop_timezone) < 0)
@@ -77,7 +97,7 @@
 {
 	struct ioloop_notify_handler_context *ctx =
 		current_ioloop->notify_handler_context;
-	int fd, ret;
+	int fd;
 
 	*io_r = NULL;
 
@@ -99,7 +119,7 @@
 		/* EINVAL means there's no realtime signals and no dnotify */
 		if (errno != EINVAL)
 			i_error("fcntl(F_SETSIG) failed: %m");
-		ctx->disabled = TRUE;
+		ioloop_dnotify_disable(ctx);
 		(void)close(fd);
 		return IO_NOTIFY_NOSUPPORT;
 	}
@@ -112,7 +132,7 @@
 			/* dnotify not in kernel. disable it. */
 			if (errno != EINVAL)
 				i_error("fcntl(F_NOTIFY) failed: %m");
-			ctx->disabled = TRUE;
+			ioloop_dnotify_disable(ctx);
 		}
 		(void)fcntl(fd, F_SETSIG, 0);
 		(void)close(fd);
@@ -179,7 +199,7 @@
 			if (errno == EINVAL) {
 				/* kernel is too old to understand even RT
 				   signals, so there's no way dnotify works */
-				ctx->disabled = TRUE;
+				ioloop_dnotify_disable(ctx);
 			} else {
 				i_fatal("sigaction(SIGRTMIN) failed: %m");
 			}
@@ -193,14 +213,7 @@
 	struct ioloop_notify_handler_context *ctx =
 		ioloop->notify_handler_context;
 
-	if (--sigrt_refcount == 0)
-		signal(SIGRTMIN, SIG_IGN);
-
-	if (close(ctx->event_pipe[0]) < 0)
-		i_error("close(event_pipe[0]) failed: %m");
-	if (close(ctx->event_pipe[1]) < 0)
-		i_error("close(event_pipe[1]) failed: %m");
-
+	ioloop_dnotify_disable(ctx);
 	i_free(ctx);
 }