fn panic_hook(info: &std::panic::PanicInfo) {
    use std::fmt::Write;

    static ALREADY_PANICKING: AtomicBool = AtomicBool::new(false);

    fn backtrace() -> String {
        let mut backtrace = String::new();
        backtrace::trace(|frame| {
            let ip = frame.ip();
            let symbol_address = frame.symbol_address();

            backtrace::resolve(ip, |symbol| {
                let mut line = format!("    {:p}", symbol_address);
                if symbol_address != ip {
                    write!(line, " ({:p})", symbol_address).unwrap();
                }
                let module = windows::module_from_address(symbol_address as *mut _);
                if let Some((name, base)) = module {
                    if let Some(fname) = Path::new(&name).file_name() {
                        write!(line, " {:?} {:p}", fname, base).unwrap();
                    } else {
                        write!(line, " {:?} {:p}", name, base).unwrap();
                    }
                }
                if let Some(name) = symbol.name() {
                    write!(line, " -- {}", name).unwrap();
                }
                if let Some(filename) = symbol.filename() {
                    if let Some(lineno) = symbol.lineno() {
                        write!(line, " -- {}:{}", filename.display(), lineno).unwrap();
                    } else {
                        write!(line, " -- {}:???", filename.display()).unwrap();
                    }
                }
                writeln!(backtrace, "{}", line).unwrap();
            });
            true // keep going to the next frame
        });
        backtrace
    }

    let already_panicking = ALREADY_PANICKING.swap(true, Ordering::Relaxed);
    if already_panicking {
        // Another thread is already panicking. This may either mean that
        // a) Two threads happened to panic simultaneously
        // or
        // b) the minidump thread started below panicked.
        // Wait a bit in case this is case a), and if the process is still alive,
        // log this panic and abort (Without writing minidump so that we don't get
        // recursive case `b`s)
        std::thread::sleep(std::time::Duration::from_millis(5000));
        debug!("Another thread panicked after the first panic:");
        return;
    }

    let mut msg = String::new();
    let location = match info.location() {
        Some(s) => format!("{}:{}", s.file(), s.line()),
        None => format!("unknown location"),
    };
    writeln!(msg, "Panic at {}", location).unwrap();
    let payload = info.payload();
    let panic_msg = match payload.downcast_ref::<&str>() {
        Some(s) => s,
        None => match payload.downcast_ref::<String>() {
            Some(s) => &s[..],
            None => "(???)",
        },
    };
    writeln!(msg, "{}", panic_msg).unwrap();
    if cfg!(debug_assertions) {
        write!(msg, "Backtrace:\n{}", backtrace()).unwrap();
    }
    error!("{}", msg);
    if !already_panicking {
        // Write minidump in a separate thread so that this thread's stack will be accurate.
        let result = std::thread::spawn(move || {
            unsafe {
                crash_dump::write_minidump_to_default_path(std::ptr::null_mut())
            }
        }).join();
        match result {
            Ok(Ok(())) => (),
            Ok(Err(e)) => {
                error!("Unable to write minidump: {}", e);
            }
            Err(_) => {
                // This should be unreachable, as this dll is being compiled to abort on panics
                error!("Minidump writing thread panicked");
            }
        }
    }
    // TODO Probs tell how to report, where to get log file etc
    windows::message_box("Shieldbattery crash :(", &format!("{}\n{}", location, panic_msg));
    unsafe {
        TerminateProcess(GetCurrentProcess(), 0x4230daef);
    }
}
// Show panic message/backtrace and terminate process before reaching the default panic handling.
// This somewhat just mimics the default Rust panic handler, but logs the error and shows a
// message box instead of trying to print to stderr, which is going to not work properly in a
// Windows GUI program like BW.
Show panic message/backtrace and terminate process before reaching the default panic handling.
This somewhat just mimics the default Rust panic handler, but logs the error and shows a
message box instead of trying to print to stderr, which is going to not work properly in a
Windows GUI program like BW.
Show panic message / backtrace and terminate process before reaching the default panic handling . This somewhat just mimics the default Rust panic handler but logs the error and shows a message box instead of trying to print to stderr which is going to not work properly in a Windows GUI program like BW .
fn panic_hook(info: &std::panic::PanicInfo) {
    use std::fmt::Write;
    static ALREADY_PANICKING: AtomicBool = AtomicBool::new(false);
    fn backtrace() -> String {
        let mut backtrace = String::new();
        backtrace::trace(|frame| {
            let ip = frame.ip();
            let symbol_address = frame.symbol_address();
            backtrace::resolve(ip, |symbol| {
                let mut line = format!("    {:p}", symbol_address);
                if symbol_address != ip {
                    write!(line, " ({:p})", symbol_address).unwrap();
                }
                let module = windows::module_from_address(symbol_address as *mut _);
                if let Some((name, base)) = module {
                    if let Some(fname) = Path::new(&name).file_name() {
                        write!(line, " {:?} {:p}", fname, base).unwrap();
                    } else {
                        write!(line, " {:?} {:p}", name, base).unwrap();
                    }
                }
                if let Some(name) = symbol.name() {
                    write!(line, " -- {}", name).unwrap();
                }
                if let Some(filename) = symbol.filename() {
                    if let Some(lineno) = symbol.lineno() {
                        write!(line, " -- {}:{}", filename.display(), lineno).unwrap();
                    } else {
                        write!(line, " -- {}:???", filename.display()).unwrap();
                    }
                }
                writeln!(backtrace, "{}", line).unwrap();
            });
            true // keep going to the next frame
        });
        backtrace
    }
    let already_panicking = ALREADY_PANICKING.swap(true, Ordering::Relaxed);
    if already_panicking {
        // Another thread is already panicking. This may either mean that
        // a) Two threads happened to panic simultaneously
        // or
        // b) the minidump thread started below panicked.
        // Wait a bit in case this is case a), and if the process is still alive,
        // log this panic and abort (Without writing minidump so that we don't get
        // recursive case `b`s)
        std::thread::sleep(std::time::Duration::from_millis(5000));
        debug!("Another thread panicked after the first panic:");
        return;
    }
    let mut msg = String::new();
    let location = match info.location() {
        Some(s) => format!("{}:{}", s.file(), s.line()),
        None => format!("unknown location"),
    };
    writeln!(msg, "Panic at {}", location).unwrap();
    let payload = info.payload();
    let panic_msg = match payload.downcast_ref::<&str>() {
        Some(s) => s,
        None => match payload.downcast_ref::<String>() {
            Some(s) => &s[..],
            None => "(???)",
        },
    };
    writeln!(msg, "{}", panic_msg).unwrap();
    if cfg!(debug_assertions) {
        write!(msg, "Backtrace:\n{}", backtrace()).unwrap();
    }
    error!("{}", msg);
    if !already_panicking {
        // Write minidump in a separate thread so that this thread's stack will be accurate.
        let result = std::thread::spawn(move || {
            unsafe {
                crash_dump::write_minidump_to_default_path(std::ptr::null_mut())
            }
        }).join();
        match result {
            Ok(Ok(())) => (),
            Ok(Err(e)) => {
                error!("Unable to write minidump: {}", e);
            }
            Err(_) => {
                // This should be unreachable, as this dll is being compiled to abort on panics
                error!("Minidump writing thread panicked");
            }
        }
    }
    // TODO Probs tell how to report, where to get log file etc
    windows::message_box("Shieldbattery crash :(", &format!("{}\n{}", location, panic_msg));
    unsafe {
        TerminateProcess(GetCurrentProcess(), 0x4230daef);
    }
}
fn panic_hook ( info : & std :: panic :: PanicInfo ) { use std :: fmt :: Write ; static ALREADY_PANICKING : AtomicBool = AtomicBool :: new ( false ) ; fn backtrace ( ) -> String { let mut backtrace = String :: new ( ) ; backtrace :: trace ( | frame | { let ip = frame . ip ( ) ; let symbol_address = frame . symbol_address ( ) ; backtrace :: resolve ( ip , | symbol | { let mut line = format ! ( " " symbol_address ) ; if symbol_address != ip { write ! ( line " " symbol_address ) . unwrap ( ) ; } let module = windows :: module_from_address ( symbol_address as * mut _ ) ; if let Some ( ( name , base ) ) = module { if let Some ( fname ) = Path :: new ( & name ) . file_name ( ) { write ! ( line " " fname base ) . unwrap ( ) ; } else { write ! ( line " " name base ) . unwrap ( ) ; } } if let Some ( name ) = symbol . name ( ) { write ! ( line " " name ) . unwrap ( ) ; } if let Some ( filename ) = symbol . filename ( ) { if let Some ( lineno ) = symbol . lineno ( ) { write ! ( line " " filename display ( ) lineno ) . unwrap ( ) ; } else { write ! ( line " " filename display ( ) ) . unwrap ( ) ; } } writeln ! ( backtrace " " line ) . unwrap ( ) ; } ) ; true // keep going to the next frame } ) ; backtrace } let already_panicking = ALREADY_PANICKING . swap ( true , Ordering :: Relaxed ) ; if already_panicking { // Another thread is already panicking. This may either mean that // a) Two threads happened to panic simultaneously // or // b) the minidump thread started below panicked. // Wait a bit in case this is case a), and if the process is still alive, // log this panic and abort (Without writing minidump so that we don't get // recursive case `b`s) std :: thread :: sleep ( std :: time :: Duration :: from_millis ( 5000 ) ) ; debug ! ( " " ) ; return ; } let mut msg = String :: new ( ) ; let location = match info . location ( ) { Some ( s ) => format ! ( " " s file ( ) s line ( ) ) , None => format ! ( " " ) , } ; writeln ! ( msg " " location ) . unwrap ( ) ; let payload = info . payload ( ) ; let panic_msg = match payload . downcast_ref :: < & str > ( ) { Some ( s ) => s , None => match payload . downcast_ref :: < String > ( ) { Some ( s ) => & s [ .. ] , None => " " , } , } ; writeln ! ( msg " " panic_msg ) . unwrap ( ) ; if cfg ! ( debug_assertions ) { write ! ( msg " \n " backtrace ( ) ) . unwrap ( ) ; } error ! ( " " msg ) ; if ! already_panicking { // Write minidump in a separate thread so that this thread's stack will be accurate. let result = std :: thread :: spawn ( move | | { unsafe { crash_dump :: write_minidump_to_default_path ( std :: ptr :: null_mut ( ) ) } } ) . join ( ) ; match result { Ok ( Ok ( ( ) ) ) => ( ) , Ok ( Err ( e ) ) => { error ! ( " " e ) ; } Err ( _ ) => { // This should be unreachable, as this dll is being compiled to abort on panics error ! ( " " ) ; } } } // TODO Probs tell how to report, where to get log file etc windows :: message_box ( " " , & format ! ( " \n " location panic_msg ) ) ; unsafe { TerminateProcess ( GetCurrentProcess ( ) , 0x4230daef ) ; } }
Show panic message/backtrace and terminate process before reaching the default panic handling.
Show panic message / backtrace and terminate process before reaching the default panic handling .
info
&std::panic::PanicInfo
info
&std::panic::PanicInfo