const std = @import("std"); const Allocator = std.mem.Allocator; const AtomicValue = std.atomic.Value; const DebugAllocator = std.heap.DebugAllocator; const Sigaction = std.posix.Sigaction; const Io = std.Io; const Threaded = Io.Threaded; const builtin = @import("builtin"); const zits = @import("zits"); const Message = zits.Server.Message; const ServerInfo = Message.ServerInfo; const Server = zits.Server; const safe_build = builtin.mode == .Debug or builtin.mode == .ReleaseSafe; var keep_running = AtomicValue(bool).init(true); fn handleSigInt(sig: std.os.linux.SIG) callconv(.c) void { _ = sig; keep_running.store(false, .monotonic); } pub fn main(outer_alloc: Allocator, server_config: ServerInfo) !void { // Configure the signal action const act = Sigaction{ .handler = .{ .handler = handleSigInt }, .mask = std.posix.sigemptyset(), .flags = 0, }; // Register the handler for SIGINT (Ctrl+C) std.posix.sigaction(std.posix.SIG.INT, &act, null); { var dba: DebugAllocator(.{}) = .init; dba.backing_allocator = outer_alloc; defer _ = dba.deinit(); const alloc = if (safe_build) dba.allocator() else outer_alloc; var threaded: Threaded = .init(alloc, .{}); defer threaded.deinit(); const io = threaded.io(); var server: Server = .{ .info = server_config, }; defer server.deinit(io, alloc); var server_task = try io.concurrent(Server.start, .{ &server, io, alloc }); defer server_task.cancel(io) catch {}; // Block until Ctrl+C while (keep_running.load(.monotonic)) { try io.sleep(.fromMilliseconds(1), .awake); } std.debug.print("\n", .{}); std.log.info("Shutting down...", .{}); server_task.cancel(io) catch {}; } std.log.info("Goodbye", .{}); }