aboutsummaryrefslogtreecommitdiff
path: root/src/crash_reporter.zig
blob: 882ec0ba6ecc6580a4fbb8f27fcfdf2a88655d6d (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
const std = @import("std");

fn setup_sigactions(act: ?*const os.Sigaction) !void {
    try os.sigaction(os.SIG.ABRT, act, null);
    try os.sigaction(os.SIG.BUS, act, null);
    try os.sigaction(os.SIG.FPE, act, null);
    try os.sigaction(os.SIG.ILL, act, null);
    try os.sigaction(os.SIG.SEGV, act, null);
    try os.sigaction(os.SIG.TRAP, act, null);
}

const builtin = @import("builtin");
const ErrorCallback = *const fn (sig: i32, addr: usize) void;
var on_error: ?ErrorCallback = null;
noinline fn sigaction_handler(sig: i32, info: *const std.os.siginfo_t, _: ?*const anyopaque) callconv(.C) void {
    // Prevent recursive calls
    setup_sigactions(null) catch unreachable;

    const addr = switch (comptime builtin.target.os.tag) {
        .linux => @intFromPtr(info.fields.sigfault.addr),
        .macos, .freebsd => @intFromPtr(info.addr),
        .netbsd => @intFromPtr(info.info.reason.fault.addr),
        .openbsd => @intFromPtr(info.data.fault.addr),
        .solaris => @intFromPtr(info.reason.fault.addr),
        else => unreachable,
    };
    if (on_error) |handle| handle(sig, addr);
}

noinline fn sigpipe_handler(_: i32, _: *const std.os.siginfo_t, _: ?*const anyopaque) callconv(.C) void {
    const bun = @import("root").bun;
    bun.Output.debug("SIGPIPE received\n", .{});
}

pub fn reloadHandlers() !void {
    try os.sigaction(os.SIG.PIPE, null, null);
    try setup_sigactions(null);

    var act = os.Sigaction{
        .handler = .{ .sigaction = sigaction_handler },
        .mask = os.empty_sigset,
        .flags = (os.SA.SIGINFO | os.SA.RESTART | os.SA.RESETHAND),
    };

    try setup_sigactions(&act);

    bun_ignore_sigpipe();
}
const os = std.os;
pub fn start() !void {
    var act = os.Sigaction{
        .handler = .{ .sigaction = sigaction_handler },
        .mask = os.empty_sigset,
        .flags = (os.SA.SIGINFO | os.SA.RESTART | os.SA.RESETHAND),
    };

    try setup_sigactions(&act);
    bun_ignore_sigpipe();
}

extern fn bun_ignore_sigpipe() void;