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);
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;
}
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);