From: Timo Sirainen Date: Tue, 2 Nov 2010 17:14:25 +0000 (+0000) Subject: imap: Fixed SELECT QRESYNC not to crash on mailbox close if a lot of changes were... X-Git-Tag: 2.0.7~38 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=23163a94645ea16faf2d557e8af61d1e39e56d95;p=thirdparty%2Fdovecot%2Fcore.git imap: Fixed SELECT QRESYNC not to crash on mailbox close if a lot of changes were being sent. --- diff --git a/src/imap/cmd-select.c b/src/imap/cmd-select.c index 073ce6665a..5951f171d3 100644 --- a/src/imap/cmd-select.c +++ b/src/imap/cmd-select.c @@ -263,11 +263,11 @@ static int select_qresync(struct imap_select_context *ctx) ctx->cmd->func = cmd_select_continue; ctx->cmd->context = ctx; - return FALSE; + return 0; } } - return imap_fetch_deinit(fetch_ctx); + return imap_fetch_deinit(fetch_ctx) < 0 ? -1 : 1; } static int @@ -276,6 +276,7 @@ select_open(struct imap_select_context *ctx, const char *mailbox, bool readonly) struct client *client = ctx->cmd->client; struct mailbox_status status; enum mailbox_flags flags = 0; + int ret; if (readonly) flags |= MAILBOX_FLAG_READONLY | MAILBOX_FLAG_KEEP_RECENT; @@ -339,13 +340,15 @@ select_open(struct imap_select_context *ctx, const char *mailbox, bool readonly) } if (ctx->qresync_uid_validity == status.uidvalidity) { - if (select_qresync(ctx) < 0) { + if ((ret = select_qresync(ctx)) < 0) { client_send_storage_error(ctx->cmd, mailbox_get_storage(ctx->box)); return -1; } + } else { + ret = 1; } - return 0; + return ret; } static void close_selected_mailbox(struct client *client) @@ -424,6 +427,8 @@ bool cmd_select_full(struct client_command_context *cmd, bool readonly) } ret = select_open(ctx, storage_name, readonly); + if (ret == 0) + return FALSE; cmd_select_finish(ctx, ret); return TRUE; } diff --git a/src/imap/imap-client.c b/src/imap/imap-client.c index 95cd8e9cb3..bc8edb8782 100644 --- a/src/imap/imap-client.c +++ b/src/imap/imap-client.c @@ -424,6 +424,8 @@ client_command_find_with_flags(struct client_command_context *new_cmd, cmd = new_cmd->client->command_queue; for (; cmd != NULL; cmd = cmd->next) { + i_warning("cmd=%s state=%d<=%d flags=%x & %x", + cmd->name, cmd->state, max_state, cmd->cmd_flags, flags); if (cmd->state <= max_state && cmd != new_cmd && (cmd->cmd_flags & flags) != 0) return cmd; diff --git a/src/imap/main.c b/src/imap/main.c index 0889fa4559..ad4d3349ec 100644 --- a/src/imap/main.c +++ b/src/imap/main.c @@ -250,6 +250,7 @@ static void login_client_connected(const struct master_login_client *client, const char *username, const char *const *extra_fields) { +#define MSG_BYE_INTERNAL_ERROR "* BYE "MAIL_ERRSTR_CRITICAL_MSG"\r\n" struct mail_storage_service_input input; const char *error; buffer_t input_buf; @@ -265,6 +266,11 @@ login_client_connected(const struct master_login_client *client, client->auth_req.data_size); if (client_create_from_input(&input, client, client->fd, client->fd, &input_buf, &error) < 0) { + if (write(client->fd, MSG_BYE_INTERNAL_ERROR, + strlen(MSG_BYE_INTERNAL_ERROR)) < 0) { + if (errno != EAGAIN && errno != EPIPE) + i_error("write(client) failed: %m"); + } i_error("%s", error); (void)close(client->fd); master_service_client_connection_destroyed(master_service);