changeset 8308:f9c44dd6dc8b 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:57:10 -0400
parents 2e24a3d8fcd9
children 2b557de3fb25
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:22:30 2009 -0400
+++ b/src/imap/client.c	Mon Jun 15 21:57:10 2009 -0400
@@ -378,6 +378,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:22:30 2009 -0400
+++ b/src/imap/commands.c	Mon Jun 15 21:57:10 2009 -0400
@@ -41,7 +41,8 @@
 #define IMAP4REV1_COMMANDS_COUNT N_ELEMENTS(imap4rev1_commands)
 
 static const struct command imap_ext_commands[] = {
-	{ "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:22:30 2009 -0400
+++ b/src/imap/commands.h	Mon Jun 15 21:57:10 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:22:30 2009 -0400
+++ b/src/imap/imap-sync.c	Mon Jun 15 21:57:10 2009 -0400
@@ -203,6 +203,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)
@@ -404,9 +416,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:22:30 2009 -0400
+++ b/src/imap/imap-sync.h	Mon Jun 15 21:57:10 2009 -0400
@@ -16,6 +16,9 @@
 int imap_sync_deinit(struct imap_sync_context *ctx);
 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,