From: Timo Sirainen Date: Thu, 3 Feb 2022 15:20:26 +0000 (+0100) Subject: anvil: Add support for KICK_TYPE_SIGNAL_WITH_SOCKET X-Git-Tag: 2.4.0~4421 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=d8eea64cbbcbb0084f607c808f865e9978cbf73d;p=thirdparty%2Fdovecot%2Fcore.git anvil: Add support for KICK_TYPE_SIGNAL_WITH_SOCKET This provides (mostly) race-free SIGTERM kick that doesn't kick the wrong user. --- diff --git a/src/anvil/anvil-connection.c b/src/anvil/anvil-connection.c index 2c773c7187..039e79a4bf 100644 --- a/src/anvil/anvil-connection.c +++ b/src/anvil/anvil-connection.c @@ -127,6 +127,9 @@ static int str_to_kick_type(const char *str, enum kick_type *kick_type_r) case 'A': *kick_type_r = KICK_TYPE_ADMIN_SOCKET; break; + case 'W': + *kick_type_r = KICK_TYPE_SIGNAL_WITH_SOCKET; + break; default: return -1; } @@ -230,8 +233,12 @@ kick_user_iter(struct anvil_connection *conn, struct connect_limit_iter *iter, } break; case KICK_TYPE_ADMIN_SOCKET: + case KICK_TYPE_SIGNAL_WITH_SOCKET: str_truncate(cmd, 0); - str_append(cmd, "KICK-USER\t"); + if (result.kick_type == KICK_TYPE_SIGNAL_WITH_SOCKET) + str_append(cmd, "KICK-USER-SIGNAL\t"); + else + str_append(cmd, "KICK-USER\t"); str_append_tabescaped(cmd, result.username); if (!guid_128_is_empty(result.conn_guid) && add_conn_guid) { @@ -244,6 +251,14 @@ kick_user_iter(struct anvil_connection *conn, struct connect_limit_iter *iter, kick->cmd_refcount++; admin_cmd_send(result.service, result.pid, str_c(cmd), kick_user_callback, kick); + if (result.kick_type == KICK_TYPE_SIGNAL_WITH_SOCKET) { + if (kill(result.pid, SIGTERM) == 0) + kick->kick_count++; + else if (errno != ESRCH) { + i_error("kill(%ld) failed: %m", + (long)result.pid); + } + } break; } prev_pid = result.pid; diff --git a/src/anvil/connect-limit.h b/src/anvil/connect-limit.h index 80492e9905..1af28acea3 100644 --- a/src/anvil/connect-limit.h +++ b/src/anvil/connect-limit.h @@ -12,6 +12,10 @@ enum kick_type { /* User kicking should be done by sending KICK-USER command to the process's admin socket or the existing anvil connection. */ KICK_TYPE_ADMIN_SOCKET, + /* Use KICK-USER command together with TERM signal. The SIGTERM handler + reads and processes the KICK-USER command. This way if there's a + race condition wrong process isn't killed. */ + KICK_TYPE_SIGNAL_WITH_SOCKET, }; struct connect_limit_key {