# HG changeset patch # User Timo Sirainen # Date 1245117382 14400 # Node ID ef7c0c3b197646b5e1581ba9aad107588b590120 # Parent 39c234ab0b219de235ab720bbf1973d7b3279d50 IMAP: Don't crash if IDLE command is pipelined after a long-running UID FETCH or UID SEARCH. diff -r 39c234ab0b21 -r ef7c0c3b1976 src/imap/client.c --- a/src/imap/client.c Mon Jun 15 21:43:37 2009 -0400 +++ b/src/imap/client.c Mon Jun 15 21:56:22 2009 -0400 @@ -391,6 +391,10 @@ CLIENT_COMMAND_STATE_WAIT_UNAMBIGUITY; bool broken_client = FALSE; + if ((cmd->cmd_flags & COMMAND_FLAG_REQUIRES_SYNC) != 0 && + !imap_sync_is_allowed(cmd->client)) + return TRUE; + if ((cmd->cmd_flags & COMMAND_FLAG_BREAKS_MAILBOX) == COMMAND_FLAG_BREAKS_MAILBOX) { /* there must be no other command running that uses the diff -r 39c234ab0b21 -r ef7c0c3b1976 src/imap/commands.c --- a/src/imap/commands.c Mon Jun 15 21:43:37 2009 -0400 +++ b/src/imap/commands.c Mon Jun 15 21:56:22 2009 -0400 @@ -44,7 +44,8 @@ { "CANCELUPDATE", cmd_cancelupdate,0 }, { "ENABLE", cmd_enable, 0 }, { "ID", cmd_id, 0 }, - { "IDLE", cmd_idle, COMMAND_FLAG_BREAKS_SEQS }, + { "IDLE", cmd_idle, COMMAND_FLAG_BREAKS_SEQS | + COMMAND_FLAG_REQUIRES_SYNC }, { "NAMESPACE", cmd_namespace, 0 }, { "SORT", cmd_sort, COMMAND_FLAG_USES_SEQS }, { "THREAD", cmd_thread, COMMAND_FLAG_USES_SEQS }, diff -r 39c234ab0b21 -r ef7c0c3b1976 src/imap/commands.h --- a/src/imap/commands.h Mon Jun 15 21:43:37 2009 -0400 +++ b/src/imap/commands.h Mon Jun 15 21:56:22 2009 -0400 @@ -20,7 +20,10 @@ /* Command uses selected mailbox */ COMMAND_FLAG_USES_MAILBOX = COMMAND_FLAG_BREAKS_MAILBOX | - COMMAND_FLAG_USES_SEQS + COMMAND_FLAG_USES_SEQS, + + /* Command requires mailbox syncing before it can do its job. */ + COMMAND_FLAG_REQUIRES_SYNC = 0x08 }; struct command { diff -r 39c234ab0b21 -r ef7c0c3b1976 src/imap/imap-sync.c --- a/src/imap/imap-sync.c Mon Jun 15 21:43:37 2009 -0400 +++ b/src/imap/imap-sync.c Mon Jun 15 21:56:22 2009 -0400 @@ -475,6 +475,18 @@ return ret; } +bool imap_sync_is_allowed(struct client *client) +{ + if (client->syncing) + return FALSE; + + if (client->mailbox != NULL && + mailbox_transaction_get_count(client->mailbox) > 0) + return FALSE; + + return TRUE; +} + static bool cmd_finish_sync(struct client_command_context *cmd) { if (cmd->sync->callback != NULL) @@ -676,9 +688,7 @@ return FALSE; } - if (client->syncing || - (client->mailbox != NULL && - mailbox_transaction_get_count(client->mailbox) > 0)) { + if (!imap_sync_is_allowed(client)) { /* wait until mailbox can be synced */ return cmd_sync_drop_fast(client); } diff -r 39c234ab0b21 -r ef7c0c3b1976 src/imap/imap-sync.h --- a/src/imap/imap-sync.h Mon Jun 15 21:43:37 2009 -0400 +++ b/src/imap/imap-sync.h Mon Jun 15 21:56:22 2009 -0400 @@ -17,6 +17,9 @@ struct client_command_context *sync_cmd); int imap_sync_more(struct imap_sync_context *ctx); +/* Returns TRUE if syncing would be allowed currently. */ +bool imap_sync_is_allowed(struct client *client); + bool cmd_sync(struct client_command_context *cmd, enum mailbox_sync_flags flags, enum imap_sync_flags imap_flags, const char *tagline); bool cmd_sync_callback(struct client_command_context *cmd,