From 56df9176b34c395b6ed7ed335a5ffe4a927eb88d Mon Sep 17 00:00:00 2001 From: Isaac Freund Date: Sat, 1 Aug 2020 17:27:49 +0200 Subject: [PATCH] server: handle SIGINT/SIGTERM with wl_event_loop This is cleaner than having a separate signal handler and should be more consistent/reliable. --- river/Root.zig | 2 +- river/Server.zig | 22 ++++++++++++++++++++-- river/main.zig | 19 +------------------ 3 files changed, 22 insertions(+), 21 deletions(-) diff --git a/river/Root.zig b/river/Root.zig index 95ab9db..c286c90 100644 --- a/river/Root.zig +++ b/river/Root.zig @@ -69,7 +69,7 @@ pub fn init(self: *Self, server: *Server) !void { self.pending_configures = 0; self.transaction_timer = c.wl_event_loop_add_timer( - self.server.wl_event_loop, + c.wl_display_get_event_loop(self.server.wl_display), handleTimeout, self, ) orelse return error.AddTimerError; diff --git a/river/Server.zig b/river/Server.zig index 66af1e7..e06e1c6 100644 --- a/river/Server.zig +++ b/river/Server.zig @@ -37,7 +37,9 @@ const ViewStack = @import("view_stack.zig").ViewStack; const XwaylandUnmanaged = @import("XwaylandUnmanaged.zig"); wl_display: *c.wl_display, -wl_event_loop: *c.wl_event_loop, + +sigint_source: *c.wl_event_source, +sigterm_source: *c.wl_event_source, wlr_backend: *c.wlr_backend, noop_backend: *c.wlr_backend, @@ -66,7 +68,13 @@ pub fn init(self: *Self) !void { errdefer c.wl_display_destroy(self.wl_display); // Never returns null if the display was created successfully - self.wl_event_loop = c.wl_display_get_event_loop(self.wl_display).?; + const wl_event_loop = c.wl_display_get_event_loop(self.wl_display); + self.sigint_source = c.wl_event_loop_add_signal(wl_event_loop, std.os.SIGINT, terminate, self.wl_display) orelse + return error.AddEventSourceFailed; + errdefer _ = c.wl_event_source_remove(self.sigint_source); + self.sigterm_source = c.wl_event_loop_add_signal(wl_event_loop, std.os.SIGTERM, terminate, self.wl_display) orelse + return error.AddEventSourceFailed; + errdefer _ = c.wl_event_source_remove(self.sigterm_source); // The wlr_backend abstracts the input/output hardware. Autocreate chooses // the best option based on the environment, for example DRM when run from @@ -129,6 +137,9 @@ pub fn init(self: *Self) !void { /// Free allocated memory and clean up pub fn deinit(self: *Self) void { // Note: order is important here + _ = c.wl_event_source_remove(self.sigint_source); + _ = c.wl_event_source_remove(self.sigterm_source); + if (build_options.xwayland) c.wlr_xwayland_destroy(self.wlr_xwayland); c.wl_display_destroy_clients(self.wl_display); @@ -157,6 +168,13 @@ pub fn run(self: Self) void { c.wl_display_run(self.wl_display); } +/// Handle SIGINT and SIGTERM by gracefully stopping the server +fn terminate(signal: c_int, data: ?*c_void) callconv(.C) c_int { + const wl_display = util.voidCast(c.wl_display, data.?); + c.wl_display_terminate(wl_display); + return 0; +} + fn handleNewOutput(listener: ?*c.wl_listener, data: ?*c_void) callconv(.C) void { const self = @fieldParentPtr(Self, "listen_new_output", listener.?); const wlr_output = util.voidCast(c.wlr_output, data.?); diff --git a/river/main.zig b/river/main.zig index 0de1856..7e47ec4 100644 --- a/river/main.zig +++ b/river/main.zig @@ -32,8 +32,6 @@ const usage: []const u8 = \\ ; -var server: Server = undefined; - pub fn main() anyerror!void { var startup_command: ?[*:0]const u8 = null; { @@ -71,15 +69,7 @@ pub fn main() anyerror!void { log.info(.server, "initializing", .{}); - // Setup a handler for SIGINT and SIGTERM so we can clean up properly - var act = std.os.Sigaction{ - .sigaction = handleSignal, - .mask = std.os.empty_sigset, - .flags = 0, - }; - std.os.sigaction(std.os.SIGINT, &act, null); - std.os.sigaction(std.os.SIGTERM, &act, null); - + var server: Server = undefined; try server.init(); defer server.deinit(); @@ -109,10 +99,3 @@ fn printErrorExit(comptime format: []const u8, args: var) noreturn { stderr.print(format ++ "\n", args) catch std.os.exit(1); std.os.exit(1); } - -fn handleSignal(sig: i32, info: *const std.os.siginfo_t, ctx_ptr: ?*const c_void) callconv(.C) void { - switch (sig) { - std.os.SIGINT, std.os.SIGTERM => c.wl_display_terminate(server.wl_display), - else => unreachable, - } -}