| ... | ... | @@ -935,42 +935,44 @@ pub fn cover_border_line(_: &mut Ui, _: f32) {} |
| 935 | 935 | pub fn with_pool( |
| 936 | 936 | run: impl FnOnce() -> Result<(), Box<dyn std::error::Error>>, |
| 937 | 937 | ) -> Result<(), Box<dyn std::error::Error>> { |
| 938 | | use std::panic; |
| 939 | | let log = log_stderr(); |
| 938 | let details = log_stderr().map(|log| format!("The log is at {}.", log.display())); |
| 940 | 939 | let (major, minor, build) = version(); |
| 941 | 940 | eprintln!( |
| 942 | 941 | "Snowbound {} on Windows {major}.{minor}.{build}", |
| 943 | 942 | option_env!("SNOWBOUND_BUILD").unwrap_or("development") |
| 944 | 943 | ); |
| 945 | | panic::set_hook(Box::new(|info| { |
| 944 | let shown = details.clone(); |
| 945 | std::panic::set_hook(Box::new(move |info| { |
| 946 | 946 | let thread = std::thread::current(); |
| 947 | 947 | let backtrace = std::backtrace::Backtrace::force_capture(); |
| 948 | 948 | eprintln!( |
| 949 | 949 | "Thread {:?} {info}\n{backtrace}", |
| 950 | 950 | thread.name().unwrap_or("") |
| 951 | 951 | ); |
| 952 | // The panic aborts the process once this returns, taking an alert's thread with it. |
| 953 | if cfg!(panic = "abort") |
| 954 | && let Some(details) = &shown |
| 955 | { |
| 956 | let text = wide(format!( |
| 957 | "Snowbound stopped because of a problem.\n\n{details}" |
| 958 | )); |
| 959 | let caption = wide("Snowbound"); |
| 960 | let style = wm::MB_OK | wm::MB_ICONWARNING; |
| 961 | unsafe { |
| 962 | wm::MessageBoxW(std::ptr::null_mut(), text.as_ptr(), caption.as_ptr(), style) |
| 963 | }; |
| 964 | } |
| 952 | 965 | })); |
| 953 | 966 | unsafe { |
| 954 | 967 | windows_sys::Win32::System::Diagnostics::Debug::AddVectoredExceptionHandler(0, Some(fault)) |
| 955 | 968 | }; |
| 956 | | let result = panic::catch_unwind(panic::AssertUnwindSafe(run)); |
| 957 | | let Some(log) = log else { |
| 958 | | return result.unwrap_or_else(|payload| panic::resume_unwind(payload)); |
| 959 | | }; |
| 960 | | let details = format!("The log is at {}.", log.display()); |
| 961 | | // The window is gone, and a message box it owned wouldn't show. |
| 962 | | WINDOW.store(0, Ordering::Relaxed); |
| 963 | | match result { |
| 964 | | Ok(Err(error)) => { |
| 965 | | alert(&error.to_string(), &details); |
| 966 | | Err(error) |
| 967 | | } |
| 968 | | Ok(done) => done, |
| 969 | | Err(payload) => { |
| 970 | | alert("Snowbound stopped because of a problem.", &details); |
| 971 | | panic::resume_unwind(payload) |
| 972 | | } |
| 969 | let result = run(); |
| 970 | if let (Err(error), Some(details)) = (&result, details) { |
| 971 | // The window is gone, and a message box it owned wouldn't show. |
| 972 | WINDOW.store(0, Ordering::Relaxed); |
| 973 | alert(&error.to_string(), &details); |
| 973 | 974 | } |
| 975 | result |
| 974 | 976 | } |
| 975 | 977 | |
| 976 | 978 | /// Points stderr at `snowbound.log` in the cache folder where it goes nowhere, keeping the |