diff --git a/components/util/lib.rs b/components/util/lib.rs index 9a06ee1b725..3f9755c4306 100644 --- a/components/util/lib.rs +++ b/components/util/lib.rs @@ -9,6 +9,7 @@ #![cfg_attr(feature = "non-geckolib", feature(decode_utf16))] #![feature(optin_builtin_traits)] #![feature(plugin)] +#![feature(panic_handler)] #![feature(reflect_marker)] #![feature(step_by)] diff --git a/components/util/thread.rs b/components/util/thread.rs index f17d6985867..d51fd3dfa37 100644 --- a/components/util/thread.rs +++ b/components/util/thread.rs @@ -5,16 +5,41 @@ use ipc_channel::ipc::IpcSender; use serde::Serialize; use std::borrow::ToOwned; +use std::io::{Write, stderr}; +use std::panic::{PanicInfo, take_handler, set_handler}; use std::sync::mpsc::Sender; use std::thread; use std::thread::Builder; use thread_state; - +#[allow(unused_must_use)] pub fn spawn_named(name: String, f: F) where F: FnOnce() + Send + 'static { let builder = thread::Builder::new().name(name); - builder.spawn(f).unwrap(); + + let f_with_handler = move || { + let hook = take_handler(); + + let new_handler = move |info: &PanicInfo| { + let payload = info.payload(); + if let Some(s) = payload.downcast_ref::() { + if s.contains("SendError") { + write!(stderr(), "Thread \"{}\" panicked with an unwrap of `SendError` (backtrace skipped)\n", + thread::current().name().unwrap_or("")); + return; + } else if s.contains("RecvError") { + write!(stderr(), "Thread \"{}\" panicked with an unwrap of `RecvError` (backtrace skipped)\n", + thread::current().name().unwrap_or("")); + return; + } + } + hook(&info); + }; + set_handler(new_handler); + f(); + }; + + builder.spawn(f_with_handler).unwrap(); } /// An abstraction over `Sender` and `IpcSender`, for use in