Zig 0.17.0-dev (Split by item)

This is an example of documentation generated by ZigDoc, an alternative to Zig's built-in Auto Doc feature. See also examples in other modes/formats. The project being documented here (as the example) is the Zig library itself.

defaultPanic

Dumps a stack trace to standard error, then aborts.

debug.defaultPanic
pub fn defaultPanic(msg: []const u8, first_trace_addr: ?usize) noreturn

File

lib/std/debug.zig:502

Code

pub fn defaultPanic(msg: []const u8, first_trace_addr: ?usize) noreturn {
    @branchHint(.cold);

    if (use_trap_panic) @trap();

    switch (builtin.os.tag) {
        .freestanding,
        .other,

        .@"3ds",
        .wiiu,
        .@"switch",

        .psx,
        .psp,
        .vita,
        => {
            @trap();
        },
        .uefi => {
            const uefi = std.os.uefi;

            var utf16_buffer: [1000]u16 = undefined;
            const len_minus_3 = std.unicode.utf8ToUtf16Le(&utf16_buffer, msg) catch 0;
            utf16_buffer[len_minus_3..][0..3].* = .{ '\r', '\n', 0 };
            const len = len_minus_3 + 3;
            const exit_msg = utf16_buffer[0 .. len - 1 :0];

            // Output to both std_err and con_out, as std_err is easier
            // to read in stuff like QEMU at times, but, unlike con_out,
            // isn't visible on actual hardware if directly booted into
            inline for ([_]?*uefi.protocol.SimpleTextOutput{ uefi.system_table.std_err, uefi.system_table.con_out }) |o| {
                if (o) |out| {
                    out.setAttribute(.{ .foreground = .red }) catch {};
                    _ = out.outputString(exit_msg) catch {};
                    out.setAttribute(.{ .foreground = .white }) catch {};
                }
            }

            if (uefi.system_table.boot_services) |bs| {
                // ExitData buffer must be allocated using boot_services.allocatePool (spec: page 220)
                const exit_data = uefi.raw_pool_allocator.dupeSentinel(u16, exit_msg, 0) catch @trap();
                bs.exit(uefi.handle, .aborted, exit_data) catch {};
            }
            @trap();
        },
        .cuda, .amdhsa => std.process.abort(),
        .plan9 => {
            var status: [std.os.plan9.ERRMAX]u8 = undefined;
            const len = @min(msg.len, status.len - 1);
            @memcpy(status[0..len], msg[0..len]);
            status[len] = 0;
            std.os.plan9.exits(status[0..len :0]);
        },
        else => {},
    }

    std.Options.debug_io.vtable.crashHandler(std.Options.debug_io.userdata);

    if (enable_segfault_handler) {
        // If a segfault happens while panicking, we want it to actually segfault, not trigger
        // the handler.
        resetSegfaultHandler();
    }

    // There is very similar logic to the following in `handleSegfault`.
    switch (panic_stage) {
        0 => {
            panic_stage = 1;
            _ = panicking.fetchAdd(1, .seq_cst);

            trace: {
                const stderr = lockStderr(&.{}).terminal();
                defer unlockStderr();
                const writer = stderr.writer;

                if (builtin.single_threaded) {
                    writer.print("panic: ", .{}) catch break :trace;
                } else {
                    const current_thread_id = std.Thread.getCurrentId();
                    writer.print("thread {d} panic: ", .{current_thread_id}) catch break :trace;
                }
                writer.print("{s}\n", .{msg}) catch break :trace;

                if (@errorReturnTrace()) |t| if (t.index > 0) {
                    writer.writeAll("error return context:\n") catch break :trace;
                    writeErrorReturnTrace(t, stderr) catch break :trace;
                    writer.writeAll("\nstack trace:\n") catch break :trace;
                };
                writeCurrentStackTrace(.{
                    .first_address = first_trace_addr orelse @returnAddress(),
                    .allow_unsafe_unwind = true, // we're crashing anyway, give it our all!
                }, stderr) catch break :trace;
            }

            waitForOtherThreadToFinishPanicking();
        },
        1 => {
            panic_stage = 2;
            // A panic happened while trying to print a previous panic message.
            // We're still holding the mutex but that's fine as we're going to
            // call abort().
            const stderr = lockStderr(&.{}).terminal();
            stderr.writer.writeAll("aborting due to recursive panic\n") catch {};
        },
        else => {}, // Panicked while printing the recursive panic message.
    }

    std.process.abort();
}