From 1425ad0caaf727418136cde776241e4cbcf59b81 Mon Sep 17 00:00:00 2001 From: Michael M Slusarz Date: Wed, 20 Jan 2021 05:09:36 +0000 Subject: [PATCH] Catch hanging commands on server side i.e. a buggy server that never sends a tagged response to a command Otherwise, imaptest will hang until the connection is terminated (which might be ~30 minutes) --- src/commands.c | 12 ++++++++++++ src/commands.h | 1 + src/imap-client.h | 2 ++ src/test-exec.c | 3 +++ 4 files changed, 18 insertions(+) diff --git a/src/commands.c b/src/commands.c index 6cdf749..7e94bb5 100644 --- a/src/commands.c +++ b/src/commands.c @@ -121,6 +121,13 @@ command_get_cmdline(struct imap_client *client, const char **_cmdline, *_cmdline_len = str_len(str); } +static void command_delay_timeout(struct imap_client *client) +{ + imap_client_input_error(client, + "Timeout while waiting for server response"); + client_disconnect(&client->client); +} + struct command *command_send(struct imap_client *client, const char *cmdline, command_callback_t *callback) { @@ -203,6 +210,10 @@ command_send_binary(struct imap_client *client, const char *cmdline, o_stream_nsendv(client->client.output, iov, 3); i_gettimeofday(&cmd->tv_start); + if (client->delay_timeout_ms > 0) + cmd->delay_to = timeout_add(client->delay_timeout_ms, + command_delay_timeout, client); + array_append(&client->commands, &cmd, 1); client->last_cmd = cmd; return cmd; @@ -231,6 +242,7 @@ void command_free(struct command *cmd) { if (array_is_created(&cmd->seq_range)) array_free(&cmd->seq_range); + timeout_remove(&cmd->delay_to); i_free(cmd->cmdline); i_free(cmd); } diff --git a/src/commands.h b/src/commands.h index e9c56a8..19550b2 100644 --- a/src/commands.h +++ b/src/commands.h @@ -26,6 +26,7 @@ struct command { command_callback_t *callback; struct timeval tv_start; + struct timeout *delay_to; bool expect_bad:1; }; diff --git a/src/imap-client.h b/src/imap-client.h index 6b8d0f4..7e584f6 100644 --- a/src/imap-client.h +++ b/src/imap-client.h @@ -74,6 +74,8 @@ struct imap_client { int (*handle_untagged)(struct imap_client *, const struct imap_arg *); + unsigned int delay_timeout_ms; + bool seen_banner:1; bool append_unfinished:1; bool try_create_mailbox:1; diff --git a/src/test-exec.c b/src/test-exec.c index 01d7856..d7c852f 100644 --- a/src/test-exec.c +++ b/src/test-exec.c @@ -23,6 +23,7 @@ #include #define IS_VAR_CHAR(c) (i_isalnum(c) || (c) == '_') +#define TEST_EXEC_DELAY_TIMEOUT_SECS 30 struct tests_execute_context { const ARRAY_TYPE(test) *tests; @@ -1320,6 +1321,8 @@ static int test_execute(const struct test *test, ctx->clients[i]->client.v.send_more_commands = test_send_lstate_commands; ctx->clients[i]->test_exec_ctx = ctx; + ctx->clients[i]->delay_timeout_ms = + TEST_EXEC_DELAY_TIMEOUT_SECS * 1000; key = i == 0 ? "user" : p_strdup_printf(pool, "user%u", i+1); value = p_strdup(pool, ctx->clients[i]->client.user->username);