mirror of
https://github.com/servo/servo.git
synced 2025-06-09 09:03:23 +00:00
Prevent the constellation from panicking if there is a deserialization error.
This commit is contained in:
parent
ddaa679f39
commit
aee1291f8e
2 changed files with 40 additions and 13 deletions
|
@ -78,8 +78,8 @@ use event_loop::EventLoop;
|
||||||
use frame::{Frame, FrameChange, FrameState, FrameTreeIterator, FullFrameTreeIterator};
|
use frame::{Frame, FrameChange, FrameState, FrameTreeIterator, FullFrameTreeIterator};
|
||||||
use gfx::font_cache_thread::FontCacheThread;
|
use gfx::font_cache_thread::FontCacheThread;
|
||||||
use gfx_traits::Epoch;
|
use gfx_traits::Epoch;
|
||||||
use ipc_channel::Error;
|
use ipc_channel::{Error as IpcError};
|
||||||
use ipc_channel::ipc::{self, IpcSender};
|
use ipc_channel::ipc::{self, IpcSender, IpcReceiver};
|
||||||
use ipc_channel::router::ROUTER;
|
use ipc_channel::router::ROUTER;
|
||||||
use layout_traits::LayoutThreadFactory;
|
use layout_traits::LayoutThreadFactory;
|
||||||
use log::{Log, LogLevel, LogLevelFilter, LogMetadata, LogRecord};
|
use log::{Log, LogLevel, LogLevelFilter, LogMetadata, LogRecord};
|
||||||
|
@ -103,6 +103,7 @@ use script_traits::{LogEntry, ServiceWorkerMsg, webdriver_msg};
|
||||||
use script_traits::{MozBrowserErrorType, MozBrowserEvent, WebDriverCommandMsg, WindowSizeData};
|
use script_traits::{MozBrowserErrorType, MozBrowserEvent, WebDriverCommandMsg, WindowSizeData};
|
||||||
use script_traits::{SWManagerMsg, ScopeThings, WindowSizeType};
|
use script_traits::{SWManagerMsg, ScopeThings, WindowSizeType};
|
||||||
use script_traits::WebVREventMsg;
|
use script_traits::WebVREventMsg;
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
use servo_config::opts;
|
use servo_config::opts;
|
||||||
use servo_config::prefs::PREFS;
|
use servo_config::prefs::PREFS;
|
||||||
use servo_rand::{Rng, SeedableRng, ServoRng, random};
|
use servo_rand::{Rng, SeedableRng, ServoRng, random};
|
||||||
|
@ -145,7 +146,7 @@ pub struct Constellation<Message, LTF, STF> {
|
||||||
|
|
||||||
/// A channel for the constellation to receive messages from script threads.
|
/// A channel for the constellation to receive messages from script threads.
|
||||||
/// This is the constellation's view of `script_sender`.
|
/// This is the constellation's view of `script_sender`.
|
||||||
script_receiver: Receiver<FromScriptMsg>,
|
script_receiver: Receiver<Result<FromScriptMsg, IpcError>>,
|
||||||
|
|
||||||
/// An IPC channel for layout threads to send messages to the constellation.
|
/// An IPC channel for layout threads to send messages to the constellation.
|
||||||
/// This is the layout threads' view of `layout_receiver`.
|
/// This is the layout threads' view of `layout_receiver`.
|
||||||
|
@ -153,7 +154,7 @@ pub struct Constellation<Message, LTF, STF> {
|
||||||
|
|
||||||
/// A channel for the constellation to receive messages from layout threads.
|
/// A channel for the constellation to receive messages from layout threads.
|
||||||
/// This is the constellation's view of `layout_sender`.
|
/// This is the constellation's view of `layout_sender`.
|
||||||
layout_receiver: Receiver<FromLayoutMsg>,
|
layout_receiver: Receiver<Result<FromLayoutMsg, IpcError>>,
|
||||||
|
|
||||||
/// A channel for the constellation to receive messages from the compositor thread.
|
/// A channel for the constellation to receive messages from the compositor thread.
|
||||||
compositor_receiver: Receiver<FromCompositorMsg>,
|
compositor_receiver: Receiver<FromCompositorMsg>,
|
||||||
|
@ -206,7 +207,7 @@ pub struct Constellation<Message, LTF, STF> {
|
||||||
/// A channel for the constellation to receive messages from the
|
/// A channel for the constellation to receive messages from the
|
||||||
/// Service Worker Manager thread. This is the constellation's view of
|
/// Service Worker Manager thread. This is the constellation's view of
|
||||||
/// `swmanager_sender`.
|
/// `swmanager_sender`.
|
||||||
swmanager_receiver: Receiver<SWManagerMsg>,
|
swmanager_receiver: Receiver<Result<SWManagerMsg, IpcError>>,
|
||||||
|
|
||||||
/// A channel for the constellation to send messages to the
|
/// A channel for the constellation to send messages to the
|
||||||
/// time profiler thread.
|
/// time profiler thread.
|
||||||
|
@ -468,6 +469,20 @@ fn log_entry(record: &LogRecord) -> Option<LogEntry> {
|
||||||
/// The number of warnings to include in each crash report.
|
/// The number of warnings to include in each crash report.
|
||||||
const WARNINGS_BUFFER_SIZE: usize = 32;
|
const WARNINGS_BUFFER_SIZE: usize = 32;
|
||||||
|
|
||||||
|
/// Route an ipc receiver to an mpsc receiver, preserving any errors.
|
||||||
|
/// This is the same as `route_ipc_receiver_to_new_mpsc_receiver`,
|
||||||
|
/// but does not panic on deserializtion errors.
|
||||||
|
fn route_ipc_receiver_to_new_mpsc_receiver_preserving_errors<T>(ipc_receiver: IpcReceiver<T>)
|
||||||
|
-> Receiver<Result<T, IpcError>>
|
||||||
|
where T: Deserialize + Serialize + Send + 'static
|
||||||
|
{
|
||||||
|
let (mpsc_sender, mpsc_receiver) = channel();
|
||||||
|
ROUTER.add_route(ipc_receiver.to_opaque(), Box::new(move |message| {
|
||||||
|
drop(mpsc_sender.send(message.to::<T>()))
|
||||||
|
}));
|
||||||
|
mpsc_receiver
|
||||||
|
}
|
||||||
|
|
||||||
impl<Message, LTF, STF> Constellation<Message, LTF, STF>
|
impl<Message, LTF, STF> Constellation<Message, LTF, STF>
|
||||||
where LTF: LayoutThreadFactory<Message=Message>,
|
where LTF: LayoutThreadFactory<Message=Message>,
|
||||||
STF: ScriptThreadFactory<Message=Message>
|
STF: ScriptThreadFactory<Message=Message>
|
||||||
|
@ -482,12 +497,12 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
|
||||||
|
|
||||||
thread::Builder::new().name("Constellation".to_owned()).spawn(move || {
|
thread::Builder::new().name("Constellation".to_owned()).spawn(move || {
|
||||||
let (ipc_script_sender, ipc_script_receiver) = ipc::channel().expect("ipc channel failure");
|
let (ipc_script_sender, ipc_script_receiver) = ipc::channel().expect("ipc channel failure");
|
||||||
let script_receiver = ROUTER.route_ipc_receiver_to_new_mpsc_receiver(ipc_script_receiver);
|
let script_receiver = route_ipc_receiver_to_new_mpsc_receiver_preserving_errors(ipc_script_receiver);
|
||||||
|
|
||||||
let (ipc_layout_sender, ipc_layout_receiver) = ipc::channel().expect("ipc channel failure");
|
let (ipc_layout_sender, ipc_layout_receiver) = ipc::channel().expect("ipc channel failure");
|
||||||
let layout_receiver = ROUTER.route_ipc_receiver_to_new_mpsc_receiver(ipc_layout_receiver);
|
let layout_receiver = route_ipc_receiver_to_new_mpsc_receiver_preserving_errors(ipc_layout_receiver);
|
||||||
|
|
||||||
let swmanager_receiver = ROUTER.route_ipc_receiver_to_new_mpsc_receiver(swmanager_receiver);
|
let swmanager_receiver = route_ipc_receiver_to_new_mpsc_receiver_preserving_errors(swmanager_receiver);
|
||||||
|
|
||||||
PipelineNamespace::install(PipelineNamespaceId(0));
|
PipelineNamespace::install(PipelineNamespaceId(0));
|
||||||
|
|
||||||
|
@ -776,13 +791,24 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
|
||||||
let receiver_from_swmanager = &self.swmanager_receiver;
|
let receiver_from_swmanager = &self.swmanager_receiver;
|
||||||
select! {
|
select! {
|
||||||
msg = receiver_from_script.recv() =>
|
msg = receiver_from_script.recv() =>
|
||||||
Request::Script(msg.expect("Unexpected script channel panic in constellation")),
|
msg.expect("Unexpected script channel panic in constellation").map(Request::Script),
|
||||||
msg = receiver_from_compositor.recv() =>
|
msg = receiver_from_compositor.recv() =>
|
||||||
Request::Compositor(msg.expect("Unexpected compositor channel panic in constellation")),
|
Ok(Request::Compositor(msg.expect("Unexpected compositor channel panic in constellation"))),
|
||||||
msg = receiver_from_layout.recv() =>
|
msg = receiver_from_layout.recv() =>
|
||||||
Request::Layout(msg.expect("Unexpected layout channel panic in constellation")),
|
msg.expect("Unexpected layout channel panic in constellation").map(Request::Layout),
|
||||||
msg = receiver_from_swmanager.recv() =>
|
msg = receiver_from_swmanager.recv() =>
|
||||||
Request::FromSWManager(msg.expect("Unexpected panic channel panic in constellation"))
|
msg.expect("Unexpected panic channel panic in constellation").map(Request::FromSWManager)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let request = match request {
|
||||||
|
Ok(request) => request,
|
||||||
|
Err(err) => {
|
||||||
|
// Treat deserialization error the same as receiving a panic message
|
||||||
|
debug!("Deserialization failed ({:?}).", err);
|
||||||
|
let reason = format!("Deserialization failed ({})", err);
|
||||||
|
let root_frame_id = self.root_frame_id;
|
||||||
|
return self.handle_panic(root_frame_id, reason, None);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1228,7 +1254,7 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
|
||||||
self.pipelines.remove(&pipeline_id);
|
self.pipelines.remove(&pipeline_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_send_error(&mut self, pipeline_id: PipelineId, err: Error) {
|
fn handle_send_error(&mut self, pipeline_id: PipelineId, err: IpcError) {
|
||||||
// Treat send error the same as receiving a panic message
|
// Treat send error the same as receiving a panic message
|
||||||
debug!("Pipeline {:?} send error ({}).", pipeline_id, err);
|
debug!("Pipeline {:?} send error ({}).", pipeline_id, err);
|
||||||
let top_level_frame_id = self.get_top_level_frame_for_pipeline(pipeline_id);
|
let top_level_frame_id = self.get_top_level_frame_for_pipeline(pipeline_id);
|
||||||
|
|
|
@ -31,6 +31,7 @@ extern crate net_traits;
|
||||||
extern crate offscreen_gl_context;
|
extern crate offscreen_gl_context;
|
||||||
extern crate profile_traits;
|
extern crate profile_traits;
|
||||||
extern crate script_traits;
|
extern crate script_traits;
|
||||||
|
extern crate serde;
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate serde_derive;
|
extern crate serde_derive;
|
||||||
extern crate servo_config;
|
extern crate servo_config;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue