summaryrefslogtreecommitdiff
path: root/src/subcommand/server.zig
blob: 1aaf57233f262e6d5f32b4da5fbf964097900d6e (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
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", .{});
}