From 1a27cfa8e337b7e3298ba230059e766cdbc1123d Mon Sep 17 00:00:00 2001 From: Timo Sirainen Date: Mon, 24 Aug 2020 19:10:43 +0300 Subject: [PATCH] imap: imap_client_hibernate() - Return reason string on failure This helps writing a unit test for it. --- src/imap/cmd-idle.c | 3 ++- src/imap/imap-client-hibernate.c | 10 +++++++++- src/imap/imap-client.h | 5 +++-- 3 files changed, 14 insertions(+), 4 deletions(-) diff --git a/src/imap/cmd-idle.c b/src/imap/cmd-idle.c index 8a05582d03..2b31dc714e 100644 --- a/src/imap/cmd-idle.c +++ b/src/imap/cmd-idle.c @@ -175,11 +175,12 @@ static void idle_add_keepalive_timeout(struct cmd_idle_context *ctx) static void idle_hibernate_timeout(struct cmd_idle_context *ctx) { struct client *client = ctx->client; + const char *reason; i_assert(ctx->sync_ctx == NULL); i_assert(!ctx->sync_pending); - if (imap_client_hibernate(&client)) { + if (imap_client_hibernate(&client, &reason)) { /* client may be destroyed now */ } else { /* failed - don't bother retrying */ diff --git a/src/imap/imap-client-hibernate.c b/src/imap/imap-client-hibernate.c index d3451b1bf6..0709e4a244 100644 --- a/src/imap/imap-client-hibernate.c +++ b/src/imap/imap-client-hibernate.c @@ -203,19 +203,23 @@ imap_hibernate_process_send(struct client *client, const buffer_t *state, return 0; } -bool imap_client_hibernate(struct client **_client) +bool imap_client_hibernate(struct client **_client, const char **reason_r) { struct client *client = *_client; buffer_t *state; const char *error; int ret, fd_notify = -1, fd_hibernate = -1; + *reason_r = NULL; + if (client->fd_in != client->fd_out) { /* we won't try to hibernate stdio clients */ + *reason_r = "stdio clients can't be hibernated"; return FALSE; } if (o_stream_get_buffer_used_size(client->output) > 0) { /* wait until we've sent the pending output to client */ + *reason_r = "output pending to client"; return FALSE; } @@ -233,11 +237,13 @@ bool imap_client_hibernate(struct client **_client) "Couldn't export state: %s (mailbox=%s)", error, client->mailbox == NULL ? "" : mailbox_get_vname(client->mailbox)); + *reason_r = error; } else if (ret == 0) { e_debug(client->event, "Couldn't hibernate imap client: " "Couldn't export state: %s (mailbox=%s)", error, client->mailbox == NULL ? "" : mailbox_get_vname(client->mailbox)); + *reason_r = error; } if (ret > 0 && client->mailbox != NULL) { fd_notify = mailbox_watch_extract_notify_fd(client->mailbox, @@ -248,6 +254,7 @@ bool imap_client_hibernate(struct client **_client) e_debug(client->event, "Couldn't hibernate imap client: " "Couldn't extract notifications fd: %s", error); + *reason_r = error; ret = -1; } } @@ -257,5 +264,6 @@ bool imap_client_hibernate(struct client **_client) e_error(client->event, "Couldn't hibernate imap client: %s", error); + *reason_r = error; ret = -1; } } diff --git a/src/imap/imap-client.h b/src/imap/imap-client.h index f2ffe0d7c9..4e591d5c7c 100644 --- a/src/imap/imap-client.h +++ b/src/imap/imap-client.h @@ -323,8 +323,9 @@ enum mailbox_feature client_enabled_mailbox_features(struct client *client); const char *const *client_enabled_features(struct client *client); /* Send client processing to imap-idle process. If successful, returns TRUE - and destroys the client. */ -bool imap_client_hibernate(struct client **client); + and destroys the client. If hibernation failed, the exact reason is + returned (mainly for unit tests). */ +bool imap_client_hibernate(struct client **client, const char **reason_r); struct imap_search_update * client_search_update_lookup(struct client *client, const char *tag,