Signal Handling
You can use Signal to listen for
operating system signals, like SIGINT or SIGTERM. The most common use for signal handling is graceful shutdown of your
application, such as a server. Unlike traditional signal handlers, these are not callbacks,
but objects that you can wait for.
There are a few ways how you can use Signal. In the simplest case, you
spawn a new task, create a Signal and wait for it to be triggered. When
the signal is received, you can stop your server gracefully. Here is an example:
var sigint = try zio.Signal.init(.interrupt);
defer sigint.deinit();
try sigint.wait(rt);
std.log.info("Received SIGINT, initiating shutdown...", .{});
server.shutdown();
You can also use Signal inside select() to wait
for multiple signals at the same time:
var sigint = try zio.Signal.init(.interrupt);
defer sigint.deinit();
var sigterm = try zio.Signal.init(.terminate);
defer sigterm.deinit();
const result = try zio.select(rt, .{
.sigint = &sigint,
.sigterm = &sigterm
});
switch (result) {
.sigint => {
std.log.info("Received SIGINT, initiating graceful shutdown...", .{});
server.shutdown(.{ .graceful = true });
},
.sigterm => {
std.log.info("Received SIGTERM, initiating shutdown...", .{});
server.shutdown(.{ .graceful = false });
},
}
Alternatively, if you have some idle main loop, you could use Signal like this:
var sigint = try zio.Signal.init(.interrupt);
defer sigint.deinit();
while (true) {
// some other work
sigint.timedWait(rt, 100 * std.time.ns_per_ms) catch |err| {
if (err == error.Timeout) {
continue;
}
return err;
};
std.log.info("Received SIGINT, initiating shutdown...", .{});
server.shutdown(.{ .graceful = true });
break;
}