changeset 7151:2ced9dd8b2cc HEAD

Use more robust command calling in output handler.
author Timo Sirainen <tss@iki.fi>
date Sat, 12 Jan 2008 07:33:15 +0200
parents 8a531386c856
children 3e506d46655f
files src/imap/client.c src/imap/client.h
diffstat 2 files changed, 22 insertions(+), 8 deletions(-) [+]
line wrap: on
line diff
--- a/src/imap/client.c	Sat Jan 12 07:16:10 2008 +0200
+++ b/src/imap/client.c	Sat Jan 12 07:33:15 2008 +0200
@@ -702,7 +702,7 @@
 
 int client_output(struct client *client)
 {
-	struct client_command_context *cmd, *next;
+	struct client_command_context *cmd;
 	int ret;
 
 	i_assert(!client->destroyed);
@@ -717,19 +717,32 @@
 		return 1;
 	}
 
+	/* mark all commands non-executed */
+	for (cmd = client->command_queue; cmd != NULL; cmd = cmd->next)
+		cmd->temp_executed = FALSE;
+
 	o_stream_cork(client->output);
-	if (client->output_lock != NULL)
+	if (client->output_lock != NULL) {
+		client->output_lock->temp_executed = TRUE;
 		client_output_cmd(client->output_lock);
-	if (client->output_lock == NULL) {
+	}
+	while (client->output_lock == NULL) {
+		/* go through the entire commands list every time in case
+		   multiple commands were freed. temp_executed keeps track of
+		   which messages we've called so far */
 		cmd = client->command_queue;
-		for (; cmd != NULL; cmd = next) {
-			next = cmd->next;
-			if (cmd->state == CLIENT_COMMAND_STATE_WAIT_OUTPUT) {
+		for (; cmd != NULL; cmd = cmd->next) {
+			if (!cmd->temp_executed &&
+			    cmd->state == CLIENT_COMMAND_STATE_WAIT_OUTPUT) {
+				cmd->temp_executed = TRUE;
 				client_output_cmd(cmd);
-				if (client->output_lock != NULL)
-					break;
+				break;
 			}
 		}
+		if (cmd == NULL) {
+			/* all commands executed */
+			break;
+		}
 	}
 	o_stream_uncork(client->output);
 
--- a/src/imap/client.h	Sat Jan 12 07:16:10 2008 +0200
+++ b/src/imap/client.h	Sat Jan 12 07:33:15 2008 +0200
@@ -49,6 +49,7 @@
 	unsigned int uid:1; /* used UID command */
 	unsigned int cancel:1; /* command is wanted to be cancelled */
 	unsigned int param_error:1;
+	unsigned int temp_executed:1; /* temporary execution state tracking */
 };
 
 struct client {