mirror of
https://github.com/servo/servo.git
synced 2025-08-02 20:20:14 +01:00
Added a dedicated panic channel.
This commit is contained in:
parent
a7c885706e
commit
cfb066ef20
13 changed files with 108 additions and 232 deletions
|
@ -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");
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue