]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
auth: Fixed user iteration hang due to earlier stream corking changes.
authorTimo Sirainen <tss@iki.fi>
Sat, 21 Sep 2013 02:03:03 +0000 (05:03 +0300)
committerTimo Sirainen <tss@iki.fi>
Sat, 21 Sep 2013 02:03:03 +0000 (05:03 +0300)
Also fixed process title updating for auth-worker process during LIST.

src/auth/auth-master-connection.c
src/auth/auth-worker-client.c

index 135b5421221ac2ff818f5b14a17f9a1bbc738549..69bdbde3c35c2207691ac48b5ea3c3a6287e9c65 100644 (file)
@@ -447,8 +447,10 @@ static int master_output_list(struct master_list_iter_ctx *ctx)
                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 @@ static void master_input_list_callback(const char *user, void *context)
        }
        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
index 1573576106218bfc475967dcf599e4abdbacf395..f5ac4608f3f0fdc6c062bacc9d4f93ce15c9f3cb 100644 (file)
@@ -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 @@ auth_worker_handle_user(struct auth_worker_client *client,
        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 @@ static void list_iter_deinit(struct auth_worker_list_context *ctx)
        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 @@ static void list_iter_callback(const char *user, void *context)
                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 @@ static void list_iter_callback(const char *user, void *context)
                }
        } 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 @@ auth_worker_handle_list(struct auth_worker_client *client,
        }
 
        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 @@ auth_worker_handle_line(struct auth_worker_client *client, const char *line)
                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 @@ static int auth_worker_output(struct auth_worker_client *client)
        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 @@ auth_worker_client_create(struct auth *auth, int fd)
        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 @@ void auth_worker_client_send_success(void)
                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)