From: Timo Sirainen Date: Thu, 23 Mar 2023 23:41:37 +0000 (+0200) Subject: imap-hibernate: If unhibernation fails, make sure imap process won't finish it later on X-Git-Tag: 2.3.21~77 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=8eb93d1c41160b87d479eb5d3d14608fc1dd3074;p=thirdparty%2Fdovecot%2Fcore.git imap-hibernate: If unhibernation fails, make sure imap process won't finish it later on Especially if unhibernation fails due to a connection timeout to imap process due to high load, it's possible that the imap process will eventually finish the unhibernation and continue with the client. This is rather confusing, since imap-hibernate process already logged that the client got disconnected. --- diff --git a/src/imap-hibernate/imap-client.c b/src/imap-hibernate/imap-client.c index 8e0f93381b..fa5eddef30 100644 --- a/src/imap-hibernate/imap-client.c +++ b/src/imap-hibernate/imap-client.c @@ -80,6 +80,7 @@ struct imap_client { bool bad_done, idle_done; bool unhibernate_queued; bool input_pending; + bool shutdown_fd_on_destroy; }; static struct imap_client *imap_clients; @@ -218,6 +219,10 @@ imap_client_move_back_send_callback(void *context, struct ostream *output) imap_client_unhibernate_failed(&client, error); return; } + /* If unhibernation fails after this, shutdown() the fd to make sure + the imap process won't later on finish unhibernation after all and + cause confusion. */ + client->shutdown_fd_on_destroy = TRUE; i_assert(ret > 0); o_stream_nsend(output, str_data(str) + 1, str_len(str) - 1); } @@ -231,6 +236,7 @@ imap_client_move_back_read_callback(void *context, const char *line) /* failed - FIXME: retry later? */ imap_client_unhibernate_failed(&client, line+1); } else { + client->shutdown_fd_on_destroy = FALSE; imap_client_destroy(&client, NULL); } } @@ -704,6 +710,11 @@ void imap_client_destroy(struct imap_client **_client, const char *reason) if (client->state.tag != NULL) i_free(client->state.tag); + if (client->shutdown_fd_on_destroy) { + if (shutdown(client->fd, SHUT_RDWR) < 0) + e_error(client->event, "shutdown() failed: %m"); + } + DLLIST_REMOVE(&imap_clients, client); imap_client_stop(client); i_stream_destroy(&client->input);