aboutsummaryrefslogtreecommitdiff
path: root/src/panic_handler.zig
blob: 84b66d9be2747d2b9314b160bd6295ddd78e051d (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
const std = @import("std");
const logger = @import("logger.zig");
const root = @import("root");
usingnamespace @import("global.zig");

/// This function is used by the Zig language code generation and
/// therefore must be kept in sync with the compiler implementation.
pub fn default_panic(msg: []const u8, error_return_trace: ?*std.builtin.StackTrace) noreturn {
    @setCold(true);
    if (@hasDecl(root, "os") and @hasDecl(root.os, "panic")) {
        root.os.panic(msg, error_return_trace);
        unreachable;
    }
    switch (std.builtin.os.tag) {
        .freestanding => {
            while (true) {
                @breakpoint();
            }
        },
        .wasi => {
            std.debug.warn("{s}", .{msg});
            std.os.abort();
        },
        .uefi => {
            // TODO look into using the debug info and logging helpful messages
            std.os.abort();
        },
        else => {
            const first_trace_addr = @returnAddress();
            std.debug.panicExtra(error_return_trace, first_trace_addr, "{s}", .{msg});
        },
    }
}

pub fn NewPanicHandler(panic_func: fn handle_panic(msg: []const u8, error_return_type: ?*std.builtin.StackTrace) noreturn) type {
    return struct {
        panic_count: usize = 0,
        skip_next_panic: bool = false,
        log: *logger.Log,

        pub var Singleton: ?*Handler = null;
        const Handler = @This();

        pub fn init(log: *logger.Log) Handler {
            return Handler{
                .log = log,
            };
        }
        pub inline fn handle_panic(msg: []const u8, error_return_type: ?*std.builtin.StackTrace) noreturn {
            Output.flush();

            if (@This().Singleton) |singleton| {
                singleton.panic_count += 1;
            }

            panic_func(msg, error_return_type);
        }
    };
}