cwist
Modern C web framework with libttak runtime
Loading...
Searching...
No Matches
shutdown.c
Go to the documentation of this file.
1
6#define _POSIX_C_SOURCE 200809L
8#include <unistd.h>
9#include <stdio.h>
10#include <stdlib.h>
11#include <stdbool.h>
12#include <cwist/sys/platform.h>
13#ifndef CWIST_PLATFORM_NO_PROC
14#include <sys/socket.h>
15#endif
16
20/* Upper bound for the post-stop connection drain. Overridable with
21 * CWIST_DRAIN_TIMEOUT (seconds; 0 skips the drain wait entirely). The drain
22 * also exits early once no C1M connection is left, so an idle server no
23 * longer sits out the full timeout on every shutdown. */
25
35 const char *env = getenv("CWIST_DRAIN_TIMEOUT");
36 if (!env || !*env) return;
37 char *end = NULL;
38 long v = strtol(env, &end, 10);
39 if (end && *end == '\0' && v >= 0 && v <= 3600) {
41 } else {
42 fprintf(stderr, "[CWIST] Ignoring invalid CWIST_DRAIN_TIMEOUT=\"%s\" (using default %d)\n",
44 }
45}
46
65 /* Take each descriptor atomically so a second request (another thread,
66 * a signal, a repeated call) cannot close a number that has meanwhile
67 * been reused for an unrelated file. */
69 if (fd >= 0) {
70#ifndef CWIST_PLATFORM_NO_PROC
71 /* close() alone does not interrupt an accept() already blocked in
72 * another thread on Linux; shutdown() makes it return (EINVAL),
73 * which the accept loops treat as the end of the server. */
74 shutdown(fd, SHUT_RDWR);
75#endif
76 close(fd);
77 }
79}
80
81#ifndef CWIST_PLATFORM_NO_PROC
86static void cwist_shutdown_handler(int sig) {
87 (void)sig;
89}
90#endif
91
92#ifndef CWIST_PLATFORM_NO_PROC
93/* What SIGTERM/SIGINT did before CWIST installed its handlers, so
94 * cwist_shutdown_restore_handlers() can put it back. Saved only on the first
95 * install after a restore: a second install would otherwise record CWIST's
96 * own handler as the previous one. */
97static struct sigaction g_prev_sigterm;
98static struct sigaction g_prev_sigint;
99static bool g_prev_saved = false;
100
112 struct sigaction sa, old_term, old_int;
113 sigemptyset(&sa.sa_mask);
114 sa.sa_flags = SA_RESTART;
115 sa.sa_handler = cwist_shutdown_handler;
116 bool term_ok = sigaction(SIGTERM, &sa, &old_term) == 0;
117 bool int_ok = sigaction(SIGINT, &sa, &old_int) == 0;
118 if (!g_prev_saved && term_ok && int_ok) {
119 g_prev_sigterm = old_term;
120 g_prev_sigint = old_int;
121 g_prev_saved = true;
122 }
123}
124
134 if (!g_prev_saved) return;
135 sigaction(SIGTERM, &g_prev_sigterm, NULL);
136 sigaction(SIGINT, &g_prev_sigint, NULL);
137 g_prev_saved = false;
138}
139#else
151 /* WASI hosts own the instance lifecycle; there are no signals to
152 * install. Shutdown is driven by the host dropping the context. */
153}
154
164#endif
165
__attribute__((constructor))
Definition alloc.c:64
size_t cap
Definition otel.c:56
Target capability macros shared by all CWIST sources.
int g_cwist_drain_timeout_sec
Drain timeout in seconds before process exits.
Definition shutdown.c:24
void cwist_shutdown_request(void)
Request a graceful shutdown of the server.
Definition shutdown.c:63
int g_cwist_listen_fd
Registered TCP listening socket (for signal-handler closure).
Definition shutdown.c:18
atomic_int g_cwist_running
Global running flag. Checked by all server event loops.
Definition shutdown.c:17
void cwist_shutdown_install_handlers(void)
Install CWIST's SIGTERM/SIGINT handlers.
Definition shutdown.c:111
void cwist_shutdown_restore_handlers(void)
Restore the SIGTERM/SIGINT handlers saved by the first cwist_shutdown_install_handlers() call.
Definition shutdown.c:133
int g_cwist_udp_fd
Registered UDP socket for HTTP/3 (for signal-handler closure).
Definition shutdown.c:19
void cwist_shutdown_reset(void)
Reset shutdown state so the process can serve again.
Definition shutdown.c:173
Unified Graceful Shutdown support for CWIST.