changeset 9136:ef7c0c3b1976 HEAD

IMAP: Don't crash if IDLE command is pipelined after a long-running UID FETCH or UID SEARCH.
author Timo Sirainen <tss@iki.fi>
date Mon, 15 Jun 2009 21:56:22 -0400
parents 39c234ab0b21
children 1d343780e009
files src/imap/client.c src/imap/commands.c src/imap/commands.h src/imap/imap-sync.c src/imap/imap-sync.h
diffstat 5 files changed, 26 insertions(+), 5 deletions(-) [+]
line wrap: on
line diff
--- 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
--- 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 },
--- 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 {
--- 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);
 	}
--- 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,