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: switch (builtin.zig_backend) { .stage2_aarch64, .stage2_arm, .stage2_powerpc, .stage2_riscv64, .stage2_spirv, .stage2_wasm, .stage2_x86, => @trap(), .stage2_x86_64 => switch (builtin.target.ofmt) { .elf, .macho => {}, else => @trap(), }, else => {}, } 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(.{ .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.dupeZ(u16, exit_msg) catch @trap(); bs.exit(uefi.handle, .aborted, exit_data) catch {}; } @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); { const stderr = lockStderrWriter(&.{}); defer unlockStderrWriter(); 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.*); dumpCurrentStackTraceToWriter(first_trace_addr orelse @returnAddress(), stderr) catch {}; } 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(). fs.File.stderr().writeAll("aborting due to recursive panic\n") catch {}; }, else => {}, // Panicked while printing the recursive panic message. }; posix.abort(); }