From d9ab4775fb18d4b91692a2870874865504df6c09 Mon Sep 17 00:00:00 2001 From: TapTap Date: Mon, 20 Jul 2026 20:27:59 +0200 Subject: [PATCH] =?UTF-8?q?fix:=20server=20shutdown=20on=20SIGTERM=20?= =?UTF-8?q?=E2=80=94=20use=20sigaction=20without=20SA=5FRESTART?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The previous code used signal() to register the cleanup handler, but on glibc (and many other modern libc implementations), signal() implicitly sets SA_RESTART, which causes blocking syscalls like accept() to be transparently restarted after the handler runs. As a result, accept() never returns EINTR, the accept loop never breaks, and the server never exits on SIGTERM/SIGINT. Fix by using sigaction() with sa_flags = 0 (no SA_RESTART), guaranteeing that accept() is interrupted and returns EINTR, allowing the loop to exit and the server to shut down cleanly. --- src/server/server.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/server/server.c b/src/server/server.c index e3957f0..21a5b4e 100644 --- a/src/server/server.c +++ b/src/server/server.c @@ -180,8 +180,12 @@ int main(int argc, char* argv[]) { log_message(LOG_LEVEL_WARNING, "--ca has no effect without --tls"); } - signal(SIGINT, cleanup); - signal(SIGTERM, cleanup); + struct sigaction sa; + sigemptyset(&sa.sa_mask); + sa.sa_handler = cleanup; + sa.sa_flags = 0; /* Do NOT set SA_RESTART — we need accept() to return EINTR */ + sigaction(SIGINT, &sa, NULL); + sigaction(SIGTERM, &sa, NULL); g_server = server_create(port); if (g_server == NULL) { log_message(LOG_LEVEL_ERROR, "Failed to create server");