From: Timo Sirainen Date: Tue, 26 May 2009 18:21:59 +0000 (-0400) Subject: imap: Cleaned up "command pending" handling code. Should fix hangs caused by recent... X-Git-Tag: 2.0.alpha1~667 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=459f60325f94f486ef057241b42d8a9e9c376fb4;p=thirdparty%2Fdovecot%2Fcore.git imap: Cleaned up "command pending" handling code. Should fix hangs caused by recent changes. --HG-- branch : HEAD --- diff --git a/src/imap/cmd-append.c b/src/imap/cmd-append.c index b37252e6fb..b89df3086b 100644 --- a/src/imap/cmd-append.c +++ b/src/imap/cmd-append.c @@ -44,7 +44,6 @@ static void client_input_append(struct client_command_context *cmd) { struct cmd_append_context *ctx = cmd->context; struct client *client = cmd->client; - struct ostream *output = client->output; bool finished; i_assert(!client->destroyed); @@ -80,17 +79,19 @@ static void client_input_append(struct client_command_context *cmd) return; } - o_stream_ref(output); - o_stream_cork(output); + o_stream_cork(client->output); finished = cmd->func(cmd); if (!finished && cmd->state != CLIENT_COMMAND_STATE_DONE) (void)client_handle_unfinished_cmd(cmd); else client_command_free(&cmd); (void)cmd_sync_delayed(client); - client_continue_pending_input(&client); - o_stream_uncork(output); - o_stream_unref(&output); + o_stream_uncork(client->output); + + if (client->disconnected) + client_destroy(client, NULL); + else + client_continue_pending_input(client); } /* Returns -1 = error, 0 = need more data, 1 = successful. flags and diff --git a/src/imap/cmd-idle.c b/src/imap/cmd-idle.c index 3e83a8adcc..6574bd67e3 100644 --- a/src/imap/cmd-idle.c +++ b/src/imap/cmd-idle.c @@ -69,7 +69,7 @@ static void idle_client_input(struct cmd_idle_context *ctx) case -2: client->input_skip_line = TRUE; idle_finish(ctx, FALSE, TRUE); - client_continue_pending_input(&client); + client_continue_pending_input(client); return; } @@ -85,10 +85,13 @@ static void idle_client_input(struct cmd_idle_context *ctx) client->input_skip_line = FALSE; else { idle_finish(ctx, strcasecmp(line, "DONE") == 0, TRUE); - client_continue_pending_input(&client); break; } } + if (client->disconnected) + client_destroy(client, NULL); + else + client_continue_pending_input(client); } static void keepalive_timeout(struct cmd_idle_context *ctx) diff --git a/src/imap/imap-client.c b/src/imap/imap-client.c index 591bdbabd0..d1b4e5ce54 100644 --- a/src/imap/imap-client.c +++ b/src/imap/imap-client.c @@ -534,20 +534,12 @@ static void client_add_missing_io(struct client *client) } } -void client_continue_pending_input(struct client **_client) +void client_continue_pending_input(struct client *client) { - struct client *client = *_client; size_t size; i_assert(!client->handling_input); - if (client->disconnected) { - if (!client->destroyed) - client_destroy(client, NULL); - *_client = NULL; - return; - } - if (client->input_lock != NULL) { /* there's a command that has locked the input */ struct client_command_context *cmd = client->input_lock; @@ -559,8 +551,10 @@ void client_continue_pending_input(struct client **_client) commands to finish. */ if (client_command_check_ambiguity(cmd)) { /* we could be waiting for existing sync to finish */ - cmd_sync_delayed(client); - return; + if (!cmd_sync_delayed(client)) + return; + if (client_command_check_ambiguity(cmd)) + return; } cmd->state = CLIENT_COMMAND_STATE_WAIT_INPUT; } @@ -569,8 +563,10 @@ void client_continue_pending_input(struct client **_client) /* if there's unread data in buffer, handle it. */ (void)i_stream_get_data(client->input, &size); - if (size > 0) - (void)client_handle_input(client); + if (size > 0 && !client->disconnected) { + if (client_handle_input(client)) + client_continue_pending_input(client); + } } /* Skip incoming data until newline is found, @@ -730,6 +726,8 @@ bool client_handle_input(struct client *client) { bool ret, remove_io, handled_commands = FALSE; + i_assert(!client->disconnected); + client->handling_input = TRUE; do { T_BEGIN { @@ -740,23 +738,16 @@ bool client_handle_input(struct client *client) } while (ret && !client->disconnected && client->io != NULL); client->handling_input = FALSE; - if (client->output->closed) { - client_destroy(client, NULL); - return TRUE; - } else { - if (remove_io) - io_remove(&client->io); - else - client_add_missing_io(client); - if (!handled_commands) - return FALSE; + if (remove_io) + io_remove(&client->io); + else + client_add_missing_io(client); + if (!handled_commands) + return FALSE; - ret = client->input_lock != NULL ? TRUE : - cmd_sync_delayed(client); - if (ret) - client_continue_pending_input(&client); - return TRUE; - } + if (client->input_lock == NULL) + cmd_sync_delayed(client); + return TRUE; } void client_input(struct client *client) @@ -793,6 +784,11 @@ void client_input(struct client *client) } o_stream_uncork(output); o_stream_unref(&output); + + if (client->disconnected) + client_destroy(client, NULL); + else + client_continue_pending_input(client); } static void client_output_cmd(struct client_command_context *cmd) @@ -855,15 +851,13 @@ int client_output(struct client *client) } } - if (client->output->closed) { + (void)cmd_sync_delayed(client); + o_stream_uncork(client->output); + if (client->disconnected) client_destroy(client, NULL); - return 1; - } else { - (void)cmd_sync_delayed(client); - o_stream_uncork(client->output); - client_continue_pending_input(&client); - return ret; - } + else + client_continue_pending_input(client); + return ret; } bool client_handle_search_save_ambiguity(struct client_command_context *cmd) diff --git a/src/imap/imap-client.h b/src/imap/imap-client.h index d86f9e167f..e40d56f5e4 100644 --- a/src/imap/imap-client.h +++ b/src/imap/imap-client.h @@ -191,7 +191,7 @@ void client_command_cancel(struct client_command_context **cmd); void client_command_free(struct client_command_context **cmd); bool client_handle_unfinished_cmd(struct client_command_context *cmd); -void client_continue_pending_input(struct client **_client); +void client_continue_pending_input(struct client *client); void client_input(struct client *client); bool client_handle_input(struct client *client); diff --git a/src/imap/imap-search.c b/src/imap/imap-search.c index e0b0e07a6d..8a979a31ca 100644 --- a/src/imap/imap-search.c +++ b/src/imap/imap-search.c @@ -439,7 +439,11 @@ static void cmd_search_more_callback(struct client_command_context *cmd) else client_command_free(&cmd); (void)cmd_sync_delayed(client); - client_continue_pending_input(&client); + + if (client->disconnected) + client_destroy(client, NULL); + else + client_continue_pending_input(client); } int cmd_search_parse_return_if_found(struct imap_search_context *ctx,