]> 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)
committerTimo Sirainen <timo.sirainen@dovecot.fi>
Wed, 4 Oct 2017 12:39:08 +0000 (15:39 +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 b7049c796e05e75c6b7979d4fcb5dfae089d73c3..423e941ed94d5236e2b3e7961f938491dc93d7bc 100644 (file)
@@ -857,6 +857,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;
@@ -872,10 +880,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
@@ -971,6 +976,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 ||