Mercurial > dovecot > core-2.2
changeset 19531:21e41add1925
imap: Fixed crash in IDLE if DONE is received while sending large output to client.
Fixes assert-crash with backtrace:
author | Timo Sirainen <timo.sirainen@dovecot.fi> |
---|---|
date | Mon, 04 Jan 2016 12:40:39 -0500 |
parents | 7104de520141 |
children | 4cd83ea1a420 |
files | src/imap/cmd-idle.c |
diffstat | 1 files changed, 10 insertions(+), 9 deletions(-) [+] |
line wrap: on
line diff
--- a/src/imap/cmd-idle.c Mon Jan 04 12:02:12 2016 -0500 +++ b/src/imap/cmd-idle.c Mon Jan 04 12:40:39 2016 -0500 @@ -136,13 +136,13 @@ idle_add_keepalive_timeout(ctx); } -static void idle_sync_now(struct mailbox *box, struct cmd_idle_context *ctx) +static bool idle_sync_now(struct mailbox *box, struct cmd_idle_context *ctx) { i_assert(ctx->sync_ctx == NULL); ctx->sync_pending = FALSE; ctx->sync_ctx = imap_sync_init(ctx->client, box, 0, 0); - (void)cmd_idle_continue(ctx->cmd); + return cmd_idle_continue(ctx->cmd); } static void idle_callback(struct mailbox *box, struct cmd_idle_context *ctx) @@ -153,7 +153,7 @@ ctx->sync_pending = TRUE; else { ctx->manual_cork = TRUE; - idle_sync_now(box, ctx); + (void)idle_sync_now(box, ctx); if (client->disconnected) client_destroy(client, NULL); } @@ -247,11 +247,11 @@ if (ctx->sync_pending) { /* more changes occurred while we were sending changes to - client */ - idle_sync_now(client->mailbox, ctx); - /* NOTE: this recurses back to this function, + client. + + NOTE: this recurses back to this function, so we return here instead of doing everything twice. */ - return FALSE; + return idle_sync_now(client->mailbox, ctx); } if (ctx->to_hibernate == NULL) idle_add_hibernate_timeout(ctx); @@ -267,10 +267,11 @@ return TRUE; } if (client->io == NULL) { - /* input is pending */ + /* input is pending. add the io back and mark the input as + pending. we can't safely read more input immediately here. */ client->io = io_add_istream(client->input, idle_client_input, ctx); - (void)idle_client_input_more(ctx); + i_stream_set_input_pending(client->input, TRUE); } return FALSE; }