aboutsummaryrefslogtreecommitdiffstats
path: root/components/util/thread.rs
diff options
context:
space:
mode:
Diffstat (limited to 'components/util/thread.rs')
-rw-r--r--components/util/thread.rs100
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");
}