dovecot-1.1: Don't try to call a cancelled command if it hasn't ...
dovecot at dovecot.org
dovecot at dovecot.org
Sat May 31 13:59:49 EEST 2008
details: http://hg.dovecot.org/dovecot-1.1/rev/a99b9735f875
changeset: 7583:a99b9735f875
user: Timo Sirainen <tss at iki.fi>
date: Sat May 31 13:59:46 2008 +0300
description:
Don't try to call a cancelled command if it hasn't started running. Cancel
the input-waiting command last. These should fix "Trying to close mailbox
with open transactions" assert when client disconnects.
diffstat:
1 file changed, 26 insertions(+), 4 deletions(-)
src/imap/client.c | 30 ++++++++++++++++++++++++++----
diffs (51 lines):
diff -r 8e7a15987428 -r a99b9735f875 src/imap/client.c
--- a/src/imap/client.c Sat May 31 13:47:11 2008 +0300
+++ b/src/imap/client.c Sat May 31 13:59:46 2008 +0300
@@ -71,8 +71,26 @@ void client_command_cancel(struct client
struct client_command_context *cmd = *_cmd;
bool cmd_ret;
- cmd->cancel = TRUE;
- cmd_ret = cmd->func == NULL ? TRUE : cmd->func(cmd);
+ switch (cmd->state) {
+ case CLIENT_COMMAND_STATE_WAIT_INPUT:
+ /* a bit kludgy check: cancel command only if it has context
+ set. currently only append command matches this check. all
+ other commands haven't even started the processing yet. */
+ if (cmd->context == NULL)
+ break;
+ /* fall through */
+ case CLIENT_COMMAND_STATE_WAIT_OUTPUT:
+ cmd->cancel = TRUE;
+ break;
+ case CLIENT_COMMAND_STATE_WAIT_UNAMBIGUITY:
+ case CLIENT_COMMAND_STATE_WAIT_SYNC:
+ /* commands haven't started yet */
+ break;
+ case CLIENT_COMMAND_STATE_DONE:
+ i_unreached();
+ }
+
+ cmd_ret = !cmd->cancel || cmd->func == NULL ? TRUE : cmd->func(cmd);
if (!cmd_ret && cmd->state != CLIENT_COMMAND_STATE_DONE) {
if (cmd->client->output->closed)
i_panic("command didn't cancel itself: %s", cmd->name);
@@ -130,12 +148,16 @@ void client_destroy(struct client *clien
/* finish off all the queued commands. */
if (client->output_lock != NULL)
client_command_cancel(&client->output_lock);
- if (client->input_lock != NULL)
- client_command_cancel(&client->input_lock);
while (client->command_queue != NULL) {
cmd = client->command_queue;
client_command_cancel(&cmd);
}
+ /* handle the input_lock command last. it might have been waiting on
+ other queued commands (although we probably should just drop the
+ command at that point since it hasn't started running. but this may
+ change in future). */
+ if (client->input_lock != NULL)
+ client_command_cancel(&client->input_lock);
if (client->mailbox != NULL)
mailbox_close(&client->mailbox);
More information about the dovecot-cvs
mailing list