dovecot-2.2: auth: Fixed user iteration hang due to earlier stre...

dovecot at dovecot.org dovecot at dovecot.org
Sat Sep 21 05:03:25 EEST 2013


details:   http://hg.dovecot.org/dovecot-2.2/rev/8b3634d4c362
changeset: 16797:8b3634d4c362
user:      Timo Sirainen <tss at iki.fi>
date:      Sat Sep 21 05:03:03 2013 +0300
description:
auth: Fixed user iteration hang due to earlier stream corking changes.
Also fixed process title updating for auth-worker process during LIST.

diffstat:

 src/auth/auth-master-connection.c |   6 +++-
 src/auth/auth-worker-client.c     |  57 ++++++++++++++++++++++++++------------
 2 files changed, 44 insertions(+), 19 deletions(-)

diffs (167 lines):

diff -r 09f5e8d6b8d4 -r 8b3634d4c362 src/auth/auth-master-connection.c
--- a/src/auth/auth-master-connection.c	Sat Sep 21 04:48:52 2013 +0300
+++ b/src/auth/auth-master-connection.c	Sat Sep 21 05:03:03 2013 +0300
@@ -447,8 +447,10 @@
 		master_input_list_finish(ctx);
 		return 1;
 	}
-	if (ret > 0)
+	if (ret > 0) {
+		o_stream_cork(ctx->conn->output);
 		userdb_blocking_iter_next(ctx->iter);
+	}
 	return 1;
 }
 
@@ -502,6 +504,8 @@
 	}
 	if (o_stream_get_buffer_used_size(ctx->conn->output) < MAX_OUTBUF_SIZE)
 		userdb_blocking_iter_next(ctx->iter);
+	else
+		o_stream_uncork(ctx->conn->output);
 }
 
 static bool
diff -r 09f5e8d6b8d4 -r 8b3634d4c362 src/auth/auth-worker-client.c
--- a/src/auth/auth-worker-client.c	Sat Sep 21 04:48:52 2013 +0300
+++ b/src/auth/auth-worker-client.c	Sat Sep 21 05:03:03 2013 +0300
@@ -19,6 +19,7 @@
 #define OUTBUF_THROTTLE_SIZE (1024*10)
 
 #define CLIENT_STATE_HANDSHAKE "handshaking"
+#define CLIENT_STATE_ITER "iterating users"
 #define CLIENT_STATE_IDLE "idling"
 #define CLIENT_STATE_STOP "waiting for shutdown"
 
@@ -413,6 +414,27 @@
 	return TRUE;
 }
 
+static void
+auth_worker_client_idle_kill(struct auth_worker_client *client ATTR_UNUSED)
+{
+	auth_worker_client_send_shutdown();
+}
+
+static void
+auth_worker_client_set_idle_timeout(struct auth_worker_client *client)
+{
+	unsigned int idle_kill_secs;
+
+	i_assert(client->to_idle == NULL);
+
+	idle_kill_secs = master_service_get_idle_kill_secs(master_service);
+	if (idle_kill_secs > 0) {
+		client->to_idle = timeout_add(idle_kill_secs * 1000,
+					      auth_worker_client_idle_kill,
+					      client);
+	}
+}
+
 static void list_iter_deinit(struct auth_worker_list_context *ctx)
 {
 	struct auth_worker_client *client = ctx->client;
@@ -429,11 +451,14 @@
 	auth_worker_send_reply(client, str);
 
 	client->io = io_add(client->fd, IO_READ, auth_worker_input, client);
-	o_stream_uncork(ctx->client->output);
+	auth_worker_client_set_idle_timeout(client);
+
 	o_stream_set_flush_callback(client->output, auth_worker_output, client);
 	auth_request_unref(&ctx->auth_request);
 	auth_worker_client_unref(&client);
 	i_free(ctx);
+
+	auth_worker_refresh_proctitle(CLIENT_STATE_IDLE);
 }
 
 static void list_iter_callback(const char *user, void *context)
@@ -449,6 +474,8 @@
 		return;
 	}
 
+	if (!ctx->sending)
+		o_stream_cork(ctx->client->output);
 	T_BEGIN {
 		str = t_str_new(128);
 		str_printfa(str, "%u\t*\t%s\n", ctx->auth_request->id, user);
@@ -476,9 +503,12 @@
 		}
 	} while (ctx->sent &&
 		 o_stream_get_buffer_used_size(ctx->client->output) <= OUTBUF_THROTTLE_SIZE);
+	o_stream_uncork(ctx->client->output);
 	ctx->sending = FALSE;
 	if (ctx->done)
 		list_iter_deinit(ctx);
+	else
+		o_stream_set_flush_pending(ctx->client->output, TRUE);
 }
 
 static int auth_worker_list_output(struct auth_worker_list_context *ctx)
@@ -528,7 +558,9 @@
 	}
 
 	io_remove(&ctx->client->io);
-	o_stream_cork(ctx->client->output);
+	if (ctx->client->to_idle != NULL)
+		timeout_remove(&ctx->client->to_idle);
+
 	o_stream_set_flush_callback(ctx->client->output,
 				    auth_worker_list_output, ctx);
 	ctx->iter = ctx->auth_request->userdb->userdb->iface->
@@ -566,7 +598,8 @@
 		i_error("BUG: Auth-worker received unknown command: %s",
 			args[1]);
 	}
-	auth_worker_refresh_proctitle(CLIENT_STATE_IDLE);
+	if (client->io != NULL)
+		auth_worker_refresh_proctitle(CLIENT_STATE_IDLE);
         return ret;
 }
 
@@ -671,17 +704,10 @@
 	return 1;
 }
 
-static void
-auth_worker_client_idle_kill(struct auth_worker_client *client ATTR_UNUSED)
-{
-	auth_worker_client_send_shutdown();
-}
-
 struct auth_worker_client *
 auth_worker_client_create(struct auth *auth, int fd)
 {
         struct auth_worker_client *client;
-	unsigned int idle_kill_secs;
 
 	client = i_new(struct auth_worker_client, 1);
 	client->refcount = 1;
@@ -694,15 +720,9 @@
 	o_stream_set_no_error_handling(client->output, TRUE);
 	o_stream_set_flush_callback(client->output, auth_worker_output, client);
 	client->io = io_add(fd, IO_READ, auth_worker_input, client);
+	auth_worker_client_set_idle_timeout(client);
 	auth_worker_refresh_proctitle(CLIENT_STATE_HANDSHAKE);
 
-	idle_kill_secs = master_service_get_idle_kill_secs(master_service);
-	if (idle_kill_secs > 0) {
-		client->to_idle = timeout_add(idle_kill_secs * 1000,
-					      auth_worker_client_idle_kill,
-					      client);
-	}
-
 	auth_worker_client = client;
 	if (auth_worker_client_error)
 		auth_worker_client_send_error();
@@ -767,7 +787,8 @@
 		o_stream_nsend_str(auth_worker_client->output, "SUCCESS\n");
 		auth_worker_client->error_sent = FALSE;
 	}
-	auth_worker_refresh_proctitle(CLIENT_STATE_IDLE);
+	if (auth_worker_client->io != NULL)
+		auth_worker_refresh_proctitle(CLIENT_STATE_IDLE);
 }
 
 void auth_worker_client_send_shutdown(void)


More information about the dovecot-cvs mailing list