111 lines
2.7 KiB
Rust
111 lines
2.7 KiB
Rust
use core::{fmt, sync::atomic::AtomicUsize};
|
|
|
|
use crate::io::{
|
|
managed::{stderr, FILE},
|
|
Write,
|
|
};
|
|
|
|
struct PanicPrinter {
|
|
buffer: [u8; 1024],
|
|
pos: usize,
|
|
|
|
print: Option<&'static mut FILE>,
|
|
}
|
|
|
|
impl fmt::Write for PanicPrinter {
|
|
fn write_str(&mut self, s: &str) -> fmt::Result {
|
|
for ch in s.bytes() {
|
|
self.push(ch);
|
|
}
|
|
Ok(())
|
|
}
|
|
}
|
|
|
|
impl PanicPrinter {
|
|
pub fn new() -> Self {
|
|
let print = unsafe { stderr.as_mut() };
|
|
|
|
Self {
|
|
buffer: [0; 1024],
|
|
pos: 0,
|
|
print,
|
|
}
|
|
}
|
|
|
|
fn flush(&mut self) {
|
|
let text = &self.buffer[..self.pos];
|
|
if !text.is_empty() {
|
|
// Print to debug trace
|
|
yggdrasil_rt::debug::trace_raw(text);
|
|
|
|
// Print to stderr
|
|
if let Some(print) = self.print.as_mut() {
|
|
print.write_all(text).ok();
|
|
print.write_all(b"\n").ok();
|
|
}
|
|
}
|
|
|
|
self.pos = 0;
|
|
}
|
|
|
|
pub fn push(&mut self, ch: u8) {
|
|
if self.pos >= self.buffer.len() {
|
|
return;
|
|
}
|
|
|
|
if ch == b'\n' {
|
|
self.flush();
|
|
} else {
|
|
self.buffer[self.pos] = ch;
|
|
self.pos += 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
#[thread_local]
|
|
static PANIC_COUNT: AtomicUsize = AtomicUsize::new(0);
|
|
|
|
#[cfg(any(not(test), rust_analyzer))]
|
|
#[panic_handler]
|
|
fn panic_handler(pi: &core::panic::PanicInfo) -> ! {
|
|
use core::{fmt::Write, sync::atomic::Ordering};
|
|
|
|
use crate::{error::EResult, process, thread::Thread};
|
|
|
|
match PANIC_COUNT.fetch_add(1, Ordering::Relaxed) {
|
|
0 => {
|
|
let mut printer = PanicPrinter::new();
|
|
|
|
writeln!(printer, "!!! ygglibc panic !!!").ok();
|
|
if let Some(location) = pi.location() {
|
|
writeln!(printer, "{}:{}:", location.file(), location.line()).ok();
|
|
}
|
|
writeln!(printer, " {}", pi.message()).ok();
|
|
|
|
let pthread_self = Thread::this();
|
|
if let EResult::Ok(this) = pthread_self {
|
|
if this == 0 {
|
|
writeln!(printer, "* Main thread panicked *").ok();
|
|
} else {
|
|
writeln!(printer, "* Thread {} panicked*", this).ok();
|
|
}
|
|
}
|
|
|
|
writeln!(printer, "Stack trace:");
|
|
crate::unwind::unwind(|frame| {
|
|
writeln!(printer, "* {:#x}", frame.pc);
|
|
true
|
|
});
|
|
|
|
printer.flush();
|
|
}
|
|
1 => {
|
|
yggdrasil_rt::debug_trace!("{pi:?}");
|
|
yggdrasil_rt::debug_trace!("!!! ygglibc panicked while panicking !!!");
|
|
}
|
|
_ => {}
|
|
}
|
|
|
|
process::abort();
|
|
}
|