| ... | @@ -935,42 +935,44 @@ pub fn cover_border_line(_: &mut Ui, _: f32) {} | ... | @@ -935,42 +935,44 @@ pub fn cover_border_line(_: &mut Ui, _: f32) {} |
| 935 | pub fn with_pool( | 935 | pub fn with_pool( |
| 936 | run: impl FnOnce() -> Result<(), Box<dyn std::error::Error>>, | 936 | run: impl FnOnce() -> Result<(), Box<dyn std::error::Error>>, |
| 937 | ) -> Result<(), Box<dyn std::error::Error>> { | 937 | ) -> Result<(), Box<dyn std::error::Error>> { |
| 938 | use std::panic; | 938 | let details = log_stderr().map(|log| format!("The log is at {}.", log.display())); |
| 939 | let log = log_stderr(); | | |
| 940 | let (major, minor, build) = version(); | 939 | let (major, minor, build) = version(); |
| 941 | eprintln!( | 940 | eprintln!( |
| 942 | "Snowbound {} on Windows {major}.{minor}.{build}", | 941 | "Snowbound {} on Windows {major}.{minor}.{build}", |
| 943 | option_env!("SNOWBOUND_BUILD").unwrap_or("development") | 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 | let thread = std::thread::current(); | 946 | let thread = std::thread::current(); |
| 947 | let backtrace = std::backtrace::Backtrace::force_capture(); | 947 | let backtrace = std::backtrace::Backtrace::force_capture(); |
| 948 | eprintln!( | 948 | eprintln!( |
| 949 | "Thread {:?} {info}\n{backtrace}", | 949 | "Thread {:?} {info}\n{backtrace}", |
| 950 | thread.name().unwrap_or("") | 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 | unsafe { | 966 | unsafe { |
| 954 | windows_sys::Win32::System::Diagnostics::Debug::AddVectoredExceptionHandler(0, Some(fault)) | 967 | windows_sys::Win32::System::Diagnostics::Debug::AddVectoredExceptionHandler(0, Some(fault)) |
| 955 | }; | 968 | }; |
| 956 | let result = panic::catch_unwind(panic::AssertUnwindSafe(run)); | 969 | let result = run(); |
| 957 | let Some(log) = log else { | 970 | if let (Err(error), Some(details)) = (&result, details) { |
| 958 | return result.unwrap_or_else(|payload| panic::resume_unwind(payload)); | 971 | // The window is gone, and a message box it owned wouldn't show. |
| 959 | }; | 972 | WINDOW.store(0, Ordering::Relaxed); |
| 960 | let details = format!("The log is at {}.", log.display()); | 973 | alert(&error.to_string(), &details); |
| 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 | } | | |
| 973 | } | 974 | } |
| | 975 | result |
| 974 | } | 976 | } |
| 975 | | 977 | |
| 976 | /// Points stderr at `snowbound.log` in the cache folder where it goes nowhere, keeping the | 978 | /// Points stderr at `snowbound.log` in the cache folder where it goes nowhere, keeping the |