changeset 21498:e74e1269959f

indexer: Don't send more requests directly from worker status callback This causes assert-crashes when workers disconnect while having multiple requests: indexer: Error: Indexer worker disconnected, discarding 2 requests for user@domain indexer: Panic: file indexer.c: line 69 (queue_try_send_more): assertion failed: (worker_connection_is_connected(conn))
author Timo Sirainen <timo.sirainen@dovecot.fi>
date Mon, 06 Feb 2017 14:05:47 +0200
parents 1f04b10661cc
children b3aa71d6fd25
files src/indexer/indexer.c
diffstat 1 files changed, 11 insertions(+), 2 deletions(-) [+]
line wrap: on
line diff
--- a/src/indexer/indexer.c	Sun Feb 05 16:49:05 2017 +0200
+++ b/src/indexer/indexer.c	Mon Feb 06 14:05:47 2017 +0200
@@ -1,6 +1,7 @@
 /* Copyright (c) 2011-2017 Dovecot authors, see the included COPYING file */
 
 #include "lib.h"
+#include "ioloop.h"
 #include "restrict-access.h"
 #include "process-title.h"
 #include "master-service.h"
@@ -18,6 +19,7 @@
 static const struct master_service_settings *set;
 static struct indexer_queue *queue;
 static struct worker_pool *worker_pool;
+static struct timeout *to_send_more;
 
 void indexer_refresh_proctitle(void)
 {
@@ -59,6 +61,9 @@
 	struct worker_connection *conn;
 	struct indexer_request *request;
 
+	if (to_send_more != NULL)
+		timeout_remove(&to_send_more);
+
 	while ((request = indexer_queue_request_peek(queue)) != NULL) {
 		conn = worker_pool_find_username_connection(worker_pool,
 							    request->username);
@@ -98,8 +103,10 @@
 	i_free(request);
 
 	/* if this was the last request for the connection, we can send more
-	   through it */
-	queue_try_send_more(queue);
+	   through it. delay it a bit, since we may be coming here from
+	   worker_connection_disconnect() and we want to finish it up. */
+	if (to_send_more == NULL)
+		to_send_more = timeout_add_short(0, queue_try_send_more, queue);
 }
 
 int main(int argc, char *argv[])
@@ -132,6 +139,8 @@
 	indexer_clients_destroy_all();
 	worker_pool_deinit(&worker_pool);
 	indexer_queue_deinit(&queue);
+	if (to_send_more != NULL)
+		timeout_remove(&to_send_more);
 
 	master_service_deinit(&master_service);
         return 0;