Mercurial > dovecot > core-2.2
changeset 19956:e038f95fdccd
director: Make sure a long-delayed kill reply for user doesn't mess up the state.
This should fix assert-crash:
director: Panic: file director.c: line 690 (director_user_kill_finish_delayed_to): assertion failed: (ctx->user->kill_state == USER_KILL_STATE_DELAY)
author | Timo Sirainen <timo.sirainen@dovecot.fi> |
---|---|
date | Thu, 24 Mar 2016 10:00:00 +0900 |
parents | 4ed6a9d7c232 |
children | 87c5013dc8e3 |
files | src/director/director.c |
diffstat | 1 files changed, 17 insertions(+), 4 deletions(-) [+] |
line wrap: on
line diff
--- a/src/director/director.c Thu Mar 24 09:43:43 2016 +0900 +++ b/src/director/director.c Thu Mar 24 10:00:00 2016 +0900 @@ -728,6 +728,8 @@ static void director_finish_user_kill(struct director *dir, struct user *user, bool self) { + i_assert(user->kill_state != USER_KILL_STATE_DELAY); + if (dir->right == NULL) { /* we're alone */ director_user_kill_finish_delayed(dir, user); @@ -748,8 +750,12 @@ struct director_kill_context *ctx = context; struct user *user; + /* 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. */ switch (state) { case IPC_CLIENT_CMD_STATE_REPLY: + /* shouldn't get here. the command reply isn't finished yet. */ return; case IPC_CLIENT_CMD_STATE_OK: break; @@ -761,14 +767,21 @@ } user = user_directory_lookup(ctx->dir->users, ctx->username_hash); - if (user == NULL || user->kill_state == USER_KILL_STATE_NONE) - return; - - director_finish_user_kill(ctx->dir, user, ctx->self); + if (user == NULL) { + /* user was already freed - ignore */ + } else if (user->kill_state == USER_KILL_STATE_KILLING || + user->kill_state == USER_KILL_STATE_KILLING_NOTIFY_RECEIVED) { + /* we were still waiting for the kill notification */ + director_finish_user_kill(ctx->dir, user, ctx->self); + } else { + /* we don't currently want to kill the user */ + } } static void director_user_move_timeout(struct user *user) { + i_assert(user->kill_state != USER_KILL_STATE_DELAY); + i_error("Finishing user %u move timed out, " "its state may now be inconsistent", user->username_hash);