]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
director: Fix tracking user move count when user is freed early
authorTimo Sirainen <timo.sirainen@dovecot.fi>
Wed, 4 Oct 2017 12:39:08 +0000 (15:39 +0300)
committerVille Savolainen <ville.savolainen@dovecot.fi>
Thu, 5 Oct 2017 10:22:13 +0000 (13:22 +0300)
users_moving_count wasn't updated if the user was freed before killing it
finished. This caused "doveadm director flush" to hang while waiting for
the move count to drop to 0, which it never did. Also following flushes
were doing less work in parallel, or possibly even nothing since director
thought there were too many users already being moved.

src/director/director.c

index 1a4b5a45a72b14cf559969d775dc8f9e494cae6e..b1ccb5fa244a438f26409f1260a194d64f1e0015 100644 (file)
@@ -835,6 +835,14 @@ director_flush_user(struct director *dir, struct user *user)
        program_client_run_async(ctx->pclient, director_flush_user_continue, ctx);
 }
 
+static void director_user_move_finished(struct director *dir)
+{
+       i_assert(dir->users_moving_count > 0);
+       dir->users_moving_count--;
+
+       director_set_state_changed(dir);
+}
+
 static void director_user_move_free(struct user *user)
 {
        struct director *dir = user->kill_ctx->dir;
@@ -851,10 +859,7 @@ static void director_user_move_free(struct user *user)
        i_free(kill_ctx);
        user->kill_ctx = NULL;
 
-       i_assert(dir->users_moving_count > 0);
-       dir->users_moving_count--;
-
-       director_set_state_changed(dir);
+       director_user_move_finished(dir);
 }
 
 static void
@@ -950,6 +955,7 @@ static void director_kill_user_callback(enum ipc_client_cmd_state state,
        if (!DIRECTOR_KILL_CONTEXT_IS_VALID(user, ctx)) {
                /* user was already freed - ignore */
                i_assert(ctx->to_move == NULL);
+               director_user_move_finished(ctx->dir);
                i_free(ctx);
        } else {
                i_assert(ctx->kill_state == USER_KILL_STATE_KILLING ||