dovecot-2.1: login proxy: Handle proxy-notify errors better.

dovecot at dovecot.org dovecot at dovecot.org
Wed Mar 7 16:58:48 EET 2012


details:   http://hg.dovecot.org/dovecot-2.1/rev/94de7605f50f
changeset: 14269:94de7605f50f
user:      Timo Sirainen <tss at iki.fi>
date:      Wed Mar 07 16:58:37 2012 +0200
description:
login proxy: Handle proxy-notify errors better.
If open() fails with ENOENT, it should still be logged as an error. If
opening or anything else fails, retry opening the fifo 60 secs.

diffstat:

 src/login-common/login-proxy-state.c |  56 ++++++++++++++++++++++++++++-------
 1 files changed, 44 insertions(+), 12 deletions(-)

diffs (126 lines):

diff -r 2026af3cf87b -r 94de7605f50f src/login-common/login-proxy-state.c
--- a/src/login-common/login-proxy-state.c	Wed Mar 07 16:48:47 2012 +0200
+++ b/src/login-common/login-proxy-state.c	Wed Mar 07 16:58:37 2012 +0200
@@ -2,6 +2,7 @@
 
 #include "lib.h"
 #include "network.h"
+#include "ioloop.h"
 #include "hash.h"
 #include "strescape.h"
 #include "fd-set-nonblock.h"
@@ -10,6 +11,8 @@
 #include <unistd.h>
 #include <fcntl.h>
 
+#define NOTIFY_RETRY_REOPEN_MSECS (60*1000)
+
 struct login_proxy_state {
 	struct hash_table *hash;
 	pool_t pool;
@@ -17,9 +20,11 @@
 	const char *notify_path;
 	int notify_fd;
 
-	unsigned int notify_fd_broken:1;
+	struct timeout *to_reopen;
 };
 
+static int login_proxy_state_notify_open(struct login_proxy_state *state);
+
 static unsigned int login_proxy_record_hash(const void *p)
 {
 	const struct login_proxy_record *rec = p;
@@ -51,16 +56,24 @@
 	return state;
 }
 
+static void login_proxy_state_close(struct login_proxy_state *state)
+{
+	if (state->notify_fd != -1) {
+		if (close(state->notify_fd) < 0)
+			i_error("close(%s) failed: %m", state->notify_path);
+		state->notify_fd = -1;
+	}
+}
+
 void login_proxy_state_deinit(struct login_proxy_state **_state)
 {
 	struct login_proxy_state *state = *_state;
 
 	*_state = NULL;
 
-	if (state->notify_fd != -1) {
-		if (close(state->notify_fd) < 0)
-			i_error("close(%s) failed: %m", state->notify_path);
-	}
+	if (state->to_reopen != NULL)
+		timeout_remove(&state->to_reopen);
+	login_proxy_state_close(state);
 	hash_table_destroy(&state->hash);
 	pool_unref(&state->pool);
 	i_free(state);
@@ -86,31 +99,39 @@
 	return rec;
 }
 
+static void login_proxy_state_reopen(struct login_proxy_state *state)
+{
+	timeout_remove(&state->to_reopen);
+	(void)login_proxy_state_notify_open(state);
+}
+
 static int login_proxy_state_notify_open(struct login_proxy_state *state)
 {
-	if (state->notify_fd_broken)
+	if (state->to_reopen != NULL) {
+		/* reopen later */
 		return -1;
+	}
 
 	state->notify_fd = open(state->notify_path, O_WRONLY);
 	if (state->notify_fd == -1) {
-		if (errno != ENOENT)
-			i_error("open(%s) failed: %m", state->notify_path);
-		state->notify_fd_broken = TRUE;
+		i_error("open(%s) failed: %m", state->notify_path);
+		state->to_reopen = timeout_add(NOTIFY_RETRY_REOPEN_MSECS,
+					       login_proxy_state_reopen, state);
 		return -1;
 	}
 	fd_set_nonblock(state->notify_fd, TRUE);
 	return 0;
 }
 
-void login_proxy_state_notify(struct login_proxy_state *state,
-			      const char *user)
+static bool login_proxy_state_try_notify(struct login_proxy_state *state,
+					 const char *user)
 {
 	unsigned int len;
 	ssize_t ret;
 
 	if (state->notify_fd == -1) {
 		if (login_proxy_state_notify_open(state) < 0)
-			return;
+			return TRUE;
 	}
 
 	T_BEGIN {
@@ -128,5 +149,16 @@
 			i_error("write(%s) wrote partial update",
 				state->notify_path);
 		}
+		login_proxy_state_close(state);
+		/* retry sending */
+		return FALSE;
 	}
+	return TRUE;
 }
+
+void login_proxy_state_notify(struct login_proxy_state *state,
+			      const char *user)
+{
+	if (!login_proxy_state_try_notify(state, user))
+		login_proxy_state_try_notify(state, user);
+}


More information about the dovecot-cvs mailing list