Function defaultPanic [src]

Dumps a stack trace to standard error, then aborts.

Prototype

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

Parameters

msg: []const u8first_trace_addr: ?usize

Source

pub fn defaultPanic( msg: []const u8, first_trace_addr: ?usize, ) noreturn { @branchHint(.cold); // For backends that cannot handle the language features depended on by the // default panic handler, we have a simpler panic handler: if (builtin.zig_backend == .stage2_wasm or builtin.zig_backend == .stage2_arm or builtin.zig_backend == .stage2_aarch64 or builtin.zig_backend == .stage2_x86 or (builtin.zig_backend == .stage2_x86_64 and (builtin.target.ofmt != .elf and builtin.target.ofmt != .macho)) or builtin.zig_backend == .stage2_sparc64 or builtin.zig_backend == .stage2_spirv64) { @trap(); } switch (builtin.os.tag) { .freestanding, .other => { @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(uefi.protocol.SimpleTextOutput.red); _ = out.outputString(exit_msg); _ = out.setAttribute(uefi.protocol.SimpleTextOutput.white); } } if (uefi.system_table.boot_services) |bs| { // ExitData buffer must be allocated using boot_services.allocatePool (spec: page 220) const exit_data: []u16 = uefi.raw_pool_allocator.alloc(u16, exit_msg.len + 1) catch @trap(); @memcpy(exit_data, exit_msg[0..exit_data.len]); // Includes null terminator. _ = bs.exit(uefi.handle, .aborted, exit_data.len, exit_data.ptr); } @trap(); }, .cuda, .amdhsa => std.posix.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 => {}, } if (enable_segfault_handler) { // If a segfault happens while panicking, we want it to actually segfault, not trigger // the handler. resetSegfaultHandler(); } // Note there is similar logic in handleSegfaultPosix and handleSegfaultWindowsExtra. nosuspend switch (panic_stage) { 0 => { panic_stage = 1; _ = panicking.fetchAdd(1, .seq_cst); { lockStdErr(); defer unlockStdErr(); const stderr = io.getStdErr().writer(); if (builtin.single_threaded) { stderr.print("panic: ", .{}) catch posix.abort(); } else { const current_thread_id = std.Thread.getCurrentId(); stderr.print("thread {} panic: ", .{current_thread_id}) catch posix.abort(); } stderr.print("{s}\n", .{msg}) catch posix.abort(); if (@errorReturnTrace()) |t| dumpStackTrace(t.*); dumpCurrentStackTrace(first_trace_addr orelse @returnAddress()); } 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(). io.getStdErr().writeAll("aborting due to recursive panic\n") catch {}; }, else => {}, // Panicked while printing the recursive panic message. }; posix.abort(); }