changeset 22997:0a2614a38fc6

director: Fix crash when user kill times out before IPC finishes Abort the IPC kick command when freeing kill context so the IPC callback won't be called.
author Timo Sirainen <timo.sirainen@dovecot.fi>
date Thu, 05 Jul 2018 14:53:02 +0300
parents fd4e4582ff6c
children 75d7b38afb60
files src/director/director.c src/director/director.h
diffstat 2 files changed, 9 insertions(+), 2 deletions(-) [+]
line wrap: on
line diff
--- a/src/director/director.c	Thu Jul 05 14:42:30 2018 +0300
+++ b/src/director/director.c	Thu Jul 05 14:53:02 2018 +0300
@@ -925,6 +925,8 @@
 	dir_debug("User %u move finished at state=%s", user->username_hash,
 		  user_kill_state_names[kill_ctx->kill_state]);
 
+	if (kill_ctx->ipc_cmd != NULL)
+		ipc_client_cmd_abort(dir->ipc_proxy, &kill_ctx->ipc_cmd);
 	if (kill_ctx->to_move != NULL)
 		timeout_remove(&kill_ctx->to_move);
 	i_free(kill_ctx->socket_path);
@@ -1003,6 +1005,9 @@
 	struct director_kill_context *ctx = context;
 	struct user *user;
 
+	/* don't try to abort the IPC command anymore */
+	ctx->ipc_cmd = NULL;
+
 	/* this is an asynchronous notification about user being killed.
 	   there are no guarantees about what might have happened to the user
 	   in the mean time. */
@@ -1107,8 +1112,8 @@
 				      user->username_hash);
 		ctx->callback_pending = TRUE;
 		dir->users_kicking_count++;
-		ipc_client_cmd(dir->ipc_proxy, cmd,
-			       director_kill_user_callback, ctx);
+		ctx->ipc_cmd = ipc_client_cmd(dir->ipc_proxy, cmd,
+					      director_kill_user_callback, ctx);
 	} else {
 		/* a) we didn't even know about the user before now.
 		   don't bother performing a local kick, since it wouldn't
--- a/src/director/director.h	Thu Jul 05 14:42:30 2018 +0300
+++ b/src/director/director.h	Thu Jul 05 14:53:02 2018 +0300
@@ -90,6 +90,8 @@
 	/* Move timeout to make sure user's connections won't silently hang
 	   indefinitely if there is some trouble moving it. */
 	struct timeout *to_move;
+	/* IPC command to kick the user */
+	struct ipc_client_cmd *ipc_cmd;
 
 	/* these are set only for director_flush_socket handling: */
 	struct ip_addr host_ip;