在长期运行的服务(如后台守护进程、网络服务器、工作流 Worker)中,捕获操作系统信号(如用户按下 Ctrl+C 触发的 SIGINT,或进程管理器发送的 SIGTERM)并进行平滑退出(Graceful Shutdown)是保障数据完整性的关键实践。
核心要点:
std.posix.Sigaction:定义信号处理行为,设置回调函数(需声明为callconv(.c))及信号掩码std.posix.sigemptyset();std.posix.sigaction(sig, &act, null):向操作系统注册指定信号的处理逻辑;- 原子标志位:在信号处理函数中,通常只进行最小限度的操作(如设置
std.atomic.Value(bool)原子标志),主循环检测到标志变化后再执行刷新缓存、关闭连接等复杂清理工作,避免信号处理函数内的竞态与死锁。
//! Demonstrate POSIX signal handling and graceful shutdown in Zig.
const builtin = @import("builtin");
const std = @import("std");
const posix = std.posix;
const print = std.debug.print;
// Atomic flag indicating whether a shutdown signal has been caught.
var should_exit = std.atomic.Value(bool).init(false);
// C-compatible signal handler function.
fn handleSignal(sig: posix.SIG) callconv(.c) void {
_ = sig;
should_exit.store(true, .monotonic);
}
pub fn main(init: std.process.Init) !void {
if (comptime builtin.os.tag == .windows) {
print("POSIX signals are not supported on Windows.\n", .{});
return;
}
const io = init.io;
// 1. Configure the signal action struct.
const act: posix.Sigaction = .{
.handler = .{ .handler = handleSignal },
.mask = posix.sigemptyset(),
.flags = 0,
};
// 2. Register signal handlers for SIGINT (Ctrl-C) and SIGTERM (kill).
posix.sigaction(posix.SIG.INT, &act, null);
posix.sigaction(posix.SIG.TERM, &act, null);
print("Signal handlers registered for SIGINT and SIGTERM.\n", .{});
// 3. For automated testing and demonstration, send SIGINT to ourselves.
// In a real server application, the loop below would run until an external signal arrives.
print("Simulating arrival of SIGINT signal...\n", .{});
try posix.kill(posix.system.getpid(), posix.SIG.INT);
// 4. Main worker loop periodically checking the shutdown flag.
while (!should_exit.load(.monotonic)) {
try std.Io.sleep(io, .fromMilliseconds(50), .awake);
}
// 5. Graceful shutdown sequence.
print("Shutdown signal detected! Starting cleanup sequence...\n", .{});
// In actual applications: flush logs, close open connections, commit pending transactions.
try std.Io.sleep(io, .fromMilliseconds(20), .awake);
print("Cleanup completed. Exiting cleanly.\n", .{});
}