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.rs89
1 files changed, 36 insertions, 53 deletions
diff --git a/components/util/thread.rs b/components/util/thread.rs
index aa0baac20aa..85a7c52adf8 100644
--- a/components/util/thread.rs
+++ b/components/util/thread.rs
@@ -3,15 +3,12 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
use ipc_channel::ipc::IpcSender;
-use opts;
+use panicking;
use serde::Serialize;
use std::any::Any;
use std::borrow::ToOwned;
-use std::io::{Write, stderr};
-use std::panic::{PanicInfo, take_hook, set_hook};
use std::sync::mpsc::Sender;
use std::thread;
-use std::thread::Builder;
use thread_state;
pub type PanicReason = Option<String>;
@@ -19,40 +16,7 @@ pub type PanicReason = Option<String>;
pub fn spawn_named<F>(name: String, f: F)
where F: FnOnce() + Send + 'static
{
- let builder = thread::Builder::new().name(name);
-
- if opts::get().full_backtraces {
- builder.spawn(f).unwrap();
- return;
- }
-
- let f_with_hook = move || {
- let hook = take_hook();
-
- let new_hook = move |info: &PanicInfo| {
- let payload = info.payload();
- if let Some(s) = payload.downcast_ref::<String>() {
- if s.contains("SendError") {
- let err = stderr();
- let _ = write!(err.lock(), "Thread \"{}\" panicked with an unwrap of \
- `SendError` (backtrace skipped)\n",
- thread::current().name().unwrap_or("<unknown thread>"));
- return;
- } else if s.contains("RecvError") {
- let err = stderr();
- let _ = write!(err.lock(), "Thread \"{}\" panicked with an unwrap of \
- `RecvError` (backtrace skipped)\n",
- thread::current().name().unwrap_or("<unknown thread>"));
- return;
- }
- }
- hook(&info);
- };
- set_hook(Box::new(new_hook));
- f();
- };
-
- builder.spawn(f_with_hook).unwrap();
+ spawn_named_with_send_on_failure_maybe(name, None, f, |_| {});
}
pub trait AddFailureDetails {
@@ -100,20 +64,39 @@ pub fn spawn_named_with_send_on_failure<F, T, S>(name: String,
S: Send + SendOnFailure + 'static,
S::Value: From<T>,
{
- let future_handle = thread::Builder::new().name(name.to_owned()).spawn(move || {
- thread_state::initialize(state);
- f()
- }).unwrap();
-
- let watcher_name = format!("{}Watcher", name);
- Builder::new().name(watcher_name).spawn(move || {
- match future_handle.join() {
- Ok(()) => (),
- Err(err) => {
- debug!("{} failed, notifying constellation", name);
- msg.add_panic_object(&*err);
- dest.send_on_failure(S::Value::from(msg));
- }
+ 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);
}
- }).unwrap();
+
+ // set the handler
+ panicking::LOCAL_INFO.with(|i| {
+ *i.borrow_mut() = Some(local);
+ });
+ f();
+ };
+
+
+ builder.spawn(f_with_state).unwrap();
}