diff options
Diffstat (limited to 'components/util/thread.rs')
-rw-r--r-- | components/util/thread.rs | 100 |
1 files changed, 18 insertions, 82 deletions
diff --git a/components/util/thread.rs b/components/util/thread.rs index 85a7c52adf8..f6bb72e20a3 100644 --- a/components/util/thread.rs +++ b/components/util/thread.rs @@ -6,97 +6,33 @@ use ipc_channel::ipc::IpcSender; use panicking; use serde::Serialize; use std::any::Any; -use std::borrow::ToOwned; -use std::sync::mpsc::Sender; use std::thread; use thread_state; -pub type PanicReason = Option<String>; - pub fn spawn_named<F>(name: String, f: F) where F: FnOnce() + Send + 'static { - spawn_named_with_send_on_failure_maybe(name, None, f, |_| {}); -} - -pub trait AddFailureDetails { - fn add_panic_message(&mut self, message: String); - fn add_panic_object(&mut self, object: &Any) { - if let Some(message) = object.downcast_ref::<String>() { - self.add_panic_message(message.to_owned()); - } else if let Some(&message) = object.downcast_ref::<&'static str>() { - self.add_panic_message(message.to_owned()); - } - } -} - -/// An abstraction over `Sender<T>` and `IpcSender<T>`, for use in -/// `spawn_named_with_send_on_failure`. -pub trait SendOnFailure { - type Value; - fn send_on_failure(&mut self, value: Self::Value); -} - -impl<T> SendOnFailure for Sender<T> where T: Send + 'static { - type Value = T; - fn send_on_failure(&mut self, value: T) { - // Discard any errors to avoid double-panic - let _ = self.send(value); - } -} - -impl<T> SendOnFailure for IpcSender<T> where T: Send + Serialize + 'static { - type Value = T; - fn send_on_failure(&mut self, value: T) { - // Discard any errors to avoid double-panic - let _ = self.send(value); - } + thread::Builder::new().name(name).spawn(f).expect("Thread spawn failed"); } /// Arrange to send a particular message to a channel if the thread fails. -pub fn spawn_named_with_send_on_failure<F, T, S>(name: String, - state: thread_state::ThreadState, - f: F, - mut msg: T, - mut dest: S) +pub fn spawn_named_with_send_on_panic<F, Id>(name: String, + state: thread_state::ThreadState, + f: F, + id: Id, + panic_chan: IpcSender<(Id, String)>) where F: FnOnce() + Send + 'static, - T: Send + AddFailureDetails + 'static, - S: Send + SendOnFailure + 'static, - S::Value: From<T>, + Id: Copy + Send + Serialize + 'static, { - spawn_named_with_send_on_failure_maybe(name, Some(state), f, - move |err| { - msg.add_panic_object(err); - dest.send_on_failure(S::Value::from(msg)); - }); -} - -fn spawn_named_with_send_on_failure_maybe<F, G>(name: String, - state: Option<thread_state::ThreadState>, - f: F, - fail: G) - where F: FnOnce() + Send + 'static, - G: FnOnce(&(Any + Send)) + Send + 'static { - - - let builder = thread::Builder::new().name(name.clone()); - - let local = panicking::PanicHandlerLocal { - fail: Box::new(fail), - }; - - let f_with_state = move || { - if let Some(state) = state { - thread_state::initialize(state); - } - - // set the handler - panicking::LOCAL_INFO.with(|i| { - *i.borrow_mut() = Some(local); - }); - f(); - }; - - - builder.spawn(f_with_state).unwrap(); + thread::Builder::new().name(name).spawn(move || { + thread_state::initialize(state); + panicking::set_thread_local_hook(Box::new(move |payload: &Any| { + debug!("Thread failed, notifying constellation"); + let reason = payload.downcast_ref::<String>().map(|s| String::from(&**s)) + .or(payload.downcast_ref::<&'static str>().map(|s| String::from(*s))) + .unwrap_or_else(|| String::from("<unknown reason>")); + let _ = panic_chan.send((id, reason)); + })); + f() + }).expect("Thread spawn failed"); } |