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