mirror of
https://github.com/servo/servo.git
synced 2025-08-05 13:40:08 +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
|
@ -25,7 +25,7 @@ use gaol;
|
|||
#[cfg(not(target_os = "windows"))]
|
||||
use gaol::sandbox::{self, Sandbox, SandboxMethods};
|
||||
use gfx::font_cache_thread::FontCacheThread;
|
||||
use gfx_traits::{Epoch, PaintMsg as FromPaintMsg};
|
||||
use gfx_traits::Epoch;
|
||||
use ipc_channel::ipc::{self, IpcOneShotServer, IpcSender};
|
||||
use ipc_channel::router::ROUTER;
|
||||
use layout_traits::{LayoutControlChan, LayoutThreadFactory};
|
||||
|
@ -34,7 +34,7 @@ use msg::constellation_msg::{FrameId, PipelineId};
|
|||
use msg::constellation_msg::{Key, KeyModifiers, KeyState, LoadData};
|
||||
use msg::constellation_msg::{PipelineNamespace, PipelineNamespaceId, NavigationDirection};
|
||||
use msg::constellation_msg::{SubpageId, WindowSizeData};
|
||||
use msg::constellation_msg::{self, ConstellationChan, Failure};
|
||||
use msg::constellation_msg::{self, ConstellationChan, PanicMsg};
|
||||
use msg::webdriver_msg;
|
||||
use net_traits::image_cache_thread::ImageCacheThread;
|
||||
use net_traits::storage_thread::{StorageThread, StorageThreadMsg};
|
||||
|
@ -95,8 +95,8 @@ pub struct Constellation<LTF, STF> {
|
|||
/// A channel through which layout thread messages can be sent to this object.
|
||||
pub layout_sender: ConstellationChan<FromLayoutMsg>,
|
||||
|
||||
/// A channel through which paint thread messages can be sent to this object.
|
||||
pub painter_sender: ConstellationChan<FromPaintMsg>,
|
||||
/// A channel through which panic messages can be sent to this object.
|
||||
pub panic_sender: ConstellationChan<PanicMsg>,
|
||||
|
||||
/// Receives messages from scripts.
|
||||
pub script_receiver: Receiver<FromScriptMsg>,
|
||||
|
@ -107,8 +107,8 @@ pub struct Constellation<LTF, STF> {
|
|||
/// Receives messages from the layout thread
|
||||
pub layout_receiver: Receiver<FromLayoutMsg>,
|
||||
|
||||
/// Receives messages from paint thread.
|
||||
pub painter_receiver: Receiver<FromPaintMsg>,
|
||||
/// Receives panic messages.
|
||||
pub panic_receiver: Receiver<PanicMsg>,
|
||||
|
||||
/// A channel (the implementation of which is port-specific) through which messages can be sent
|
||||
/// to the compositor.
|
||||
|
@ -320,19 +320,19 @@ impl<LTF: LayoutThreadFactory, STF: ScriptThreadFactory> Constellation<LTF, STF>
|
|||
let (compositor_sender, compositor_receiver) = channel();
|
||||
let (ipc_layout_receiver, ipc_layout_sender) = ConstellationChan::<FromLayoutMsg>::new();
|
||||
let layout_receiver = ROUTER.route_ipc_receiver_to_new_mpsc_receiver(ipc_layout_receiver);
|
||||
let (ipc_painter_receiver, ipc_painter_sender) = ConstellationChan::<FromPaintMsg>::new();
|
||||
let painter_receiver = ROUTER.route_ipc_receiver_to_new_mpsc_receiver(ipc_painter_receiver);
|
||||
let (ipc_panic_receiver, ipc_panic_sender) = ConstellationChan::<PanicMsg>::new();
|
||||
let panic_receiver = ROUTER.route_ipc_receiver_to_new_mpsc_receiver(ipc_panic_receiver);
|
||||
let compositor_sender_clone = compositor_sender.clone();
|
||||
spawn_named("Constellation".to_owned(), move || {
|
||||
let mut constellation: Constellation<LTF, STF> = Constellation {
|
||||
script_sender: ipc_script_sender,
|
||||
compositor_sender: compositor_sender_clone,
|
||||
layout_sender: ipc_layout_sender,
|
||||
painter_sender: ipc_painter_sender,
|
||||
script_receiver: script_receiver,
|
||||
panic_sender: ipc_panic_sender,
|
||||
compositor_receiver: compositor_receiver,
|
||||
layout_receiver: layout_receiver,
|
||||
painter_receiver: painter_receiver,
|
||||
panic_receiver: panic_receiver,
|
||||
compositor_proxy: state.compositor_proxy,
|
||||
devtools_chan: state.devtools_chan,
|
||||
resource_thread: state.resource_thread,
|
||||
|
@ -416,7 +416,7 @@ impl<LTF: LayoutThreadFactory, STF: ScriptThreadFactory> Constellation<LTF, STF>
|
|||
parent_info: parent_info,
|
||||
constellation_chan: self.script_sender.clone(),
|
||||
layout_to_constellation_chan: self.layout_sender.clone(),
|
||||
painter_chan: self.painter_sender.clone(),
|
||||
panic_chan: self.panic_sender.clone(),
|
||||
scheduler_chan: self.scheduler_chan.clone(),
|
||||
compositor_proxy: self.compositor_proxy.clone_compositor_proxy(),
|
||||
devtools_chan: self.devtools_chan.clone(),
|
||||
|
@ -548,7 +548,7 @@ impl<LTF: LayoutThreadFactory, STF: ScriptThreadFactory> Constellation<LTF, STF>
|
|||
Script(FromScriptMsg),
|
||||
Compositor(FromCompositorMsg),
|
||||
Layout(FromLayoutMsg),
|
||||
Paint(FromPaintMsg)
|
||||
Panic(PanicMsg)
|
||||
}
|
||||
|
||||
// Get one incoming request.
|
||||
|
@ -566,16 +566,16 @@ impl<LTF: LayoutThreadFactory, STF: ScriptThreadFactory> Constellation<LTF, STF>
|
|||
let receiver_from_script = &self.script_receiver;
|
||||
let receiver_from_compositor = &self.compositor_receiver;
|
||||
let receiver_from_layout = &self.layout_receiver;
|
||||
let receiver_from_paint = &self.painter_receiver;
|
||||
let receiver_from_panic = &self.panic_receiver;
|
||||
select! {
|
||||
msg = receiver_from_script.recv() =>
|
||||
Request::Script(msg.expect("Unexpected script failure in constellation")),
|
||||
Request::Script(msg.expect("Unexpected script channel panic in constellation")),
|
||||
msg = receiver_from_compositor.recv() =>
|
||||
Request::Compositor(msg.expect("Unexpected compositor failure in constellation")),
|
||||
Request::Compositor(msg.expect("Unexpected compositor channel panic in constellation")),
|
||||
msg = receiver_from_layout.recv() =>
|
||||
Request::Layout(msg.expect("Unexpected layout failure in constellation")),
|
||||
msg = receiver_from_paint.recv() =>
|
||||
Request::Paint(msg.expect("Unexpected paint failure in constellation"))
|
||||
Request::Layout(msg.expect("Unexpected layout channel panic in constellation")),
|
||||
msg = receiver_from_panic.recv() =>
|
||||
Request::Panic(msg.expect("Unexpected panic channel panic in constellation"))
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -655,10 +655,6 @@ impl<LTF: LayoutThreadFactory, STF: ScriptThreadFactory> Constellation<LTF, STF>
|
|||
// Messages from script
|
||||
|
||||
|
||||
Request::Script(FromScriptMsg::Failure(failure)) => {
|
||||
debug!("handling script failure message from pipeline {:?}", failure);
|
||||
self.handle_failure_msg(failure);
|
||||
}
|
||||
Request::Script(FromScriptMsg::ScriptLoadedURLInIFrame(load_info)) => {
|
||||
debug!("constellation got iframe URL load message {:?} {:?} {:?}",
|
||||
load_info.containing_pipeline_id,
|
||||
|
@ -803,10 +799,6 @@ impl<LTF: LayoutThreadFactory, STF: ScriptThreadFactory> Constellation<LTF, STF>
|
|||
Request::Layout(FromLayoutMsg::ChangeRunningAnimationsState(pipeline_id, animation_state)) => {
|
||||
self.handle_change_running_animations_state(pipeline_id, animation_state)
|
||||
}
|
||||
Request::Layout(FromLayoutMsg::Failure(failure)) => {
|
||||
debug!("handling paint failure message from pipeline {:?}", failure);
|
||||
self.handle_failure_msg(failure);
|
||||
}
|
||||
Request::Layout(FromLayoutMsg::SetCursor(cursor)) => {
|
||||
self.handle_set_cursor_msg(cursor)
|
||||
}
|
||||
|
@ -816,15 +808,12 @@ impl<LTF: LayoutThreadFactory, STF: ScriptThreadFactory> Constellation<LTF, STF>
|
|||
}
|
||||
|
||||
|
||||
// Messages from paint thread
|
||||
// Panic messages
|
||||
|
||||
|
||||
// Notification that painting has finished and is requesting permission to paint.
|
||||
Request::Paint(FromPaintMsg::Failure(failure)) => {
|
||||
debug!("handling paint failure message from pipeline {:?}", failure);
|
||||
self.handle_failure_msg(failure);
|
||||
Request::Panic((pipeline_id, panic_reason)) => {
|
||||
debug!("handling panic message ({:?})", pipeline_id);
|
||||
self.handle_panic(pipeline_id, panic_reason);
|
||||
}
|
||||
|
||||
}
|
||||
true
|
||||
}
|
||||
|
@ -851,17 +840,12 @@ impl<LTF: LayoutThreadFactory, STF: ScriptThreadFactory> Constellation<LTF, STF>
|
|||
}
|
||||
|
||||
fn handle_send_error(&mut self, pipeline_id: PipelineId, err: IOError) {
|
||||
let parent_info = match self.pipelines.get(&pipeline_id) {
|
||||
None => return warn!("Pipeline {:?} send error after closure.", pipeline_id),
|
||||
Some(pipeline) => pipeline.parent_info,
|
||||
};
|
||||
// Treat send error the same as receiving a failure message
|
||||
// Treat send error the same as receiving a panic message
|
||||
debug!("Pipeline {:?} send error ({}).", pipeline_id, err);
|
||||
let failure = Failure::new(pipeline_id, parent_info);
|
||||
self.handle_failure_msg(failure);
|
||||
self.handle_panic(Some(pipeline_id), format!("Send failed ({})", err));
|
||||
}
|
||||
|
||||
fn handle_failure_msg(&mut self, failure: Failure) {
|
||||
fn handle_panic(&mut self, pipeline_id: Option<PipelineId>, reason: String) {
|
||||
if opts::get().hard_fail {
|
||||
// It's quite difficult to make Servo exit cleanly if some threads have failed.
|
||||
// Hard fail exists for test runners so we crash and that's good enough.
|
||||
|
@ -871,15 +855,26 @@ impl<LTF: LayoutThreadFactory, STF: ScriptThreadFactory> Constellation<LTF, STF>
|
|||
process::exit(1);
|
||||
}
|
||||
|
||||
let window_size = self.pipelines.get(&failure.pipeline_id).and_then(|pipeline| pipeline.size);
|
||||
debug!("Panic handler for pipeline {:?}: {}.", pipeline_id, reason);
|
||||
|
||||
if let Some(pipeline_id) = pipeline_id {
|
||||
self.replace_pipeline_with_about_failure(pipeline_id);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
fn replace_pipeline_with_about_failure(&mut self, pipeline_id: PipelineId) {
|
||||
|
||||
let parent_info = self.pipelines.get(&pipeline_id).and_then(|pipeline| pipeline.parent_info);
|
||||
let window_size = self.pipelines.get(&pipeline_id).and_then(|pipeline| pipeline.size);
|
||||
|
||||
// Notify the browser chrome that the pipeline has failed
|
||||
self.trigger_mozbrowsererror(failure.pipeline_id);
|
||||
self.trigger_mozbrowsererror(pipeline_id);
|
||||
|
||||
self.close_pipeline(failure.pipeline_id, ExitPipelineMode::Force);
|
||||
self.close_pipeline(pipeline_id, ExitPipelineMode::Force);
|
||||
|
||||
while let Some(pending_pipeline_id) = self.pending_frames.iter().find(|pending| {
|
||||
pending.old_pipeline_id == Some(failure.pipeline_id)
|
||||
pending.old_pipeline_id == Some(pipeline_id)
|
||||
}).map(|frame| frame.new_pipeline_id) {
|
||||
warn!("removing pending frame change for failed pipeline");
|
||||
self.close_pipeline(pending_pipeline_id, ExitPipelineMode::Force);
|
||||
|
@ -889,12 +884,12 @@ impl<LTF: LayoutThreadFactory, STF: ScriptThreadFactory> Constellation<LTF, STF>
|
|||
|
||||
let new_pipeline_id = PipelineId::new();
|
||||
self.new_pipeline(new_pipeline_id,
|
||||
failure.parent_info,
|
||||
parent_info,
|
||||
window_size,
|
||||
None,
|
||||
LoadData::new(Url::parse("about:failure").expect("infallible")));
|
||||
|
||||
self.push_pending_frame(new_pipeline_id, Some(failure.pipeline_id));
|
||||
self.push_pending_frame(new_pipeline_id, Some(pipeline_id));
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -10,12 +10,11 @@ use euclid::scale_factor::ScaleFactor;
|
|||
use euclid::size::TypedSize2D;
|
||||
use gfx::font_cache_thread::FontCacheThread;
|
||||
use gfx::paint_thread::{ChromeToPaintMsg, LayoutToPaintMsg, PaintThread};
|
||||
use gfx_traits::PaintMsg;
|
||||
use ipc_channel::ipc::{self, IpcReceiver, IpcSender};
|
||||
use ipc_channel::router::ROUTER;
|
||||
use layers::geometry::DevicePixel;
|
||||
use layout_traits::{LayoutControlChan, LayoutThreadFactory};
|
||||
use msg::constellation_msg::{ConstellationChan, Failure, FrameId, PipelineId, SubpageId};
|
||||
use msg::constellation_msg::{ConstellationChan, PanicMsg, FrameId, PipelineId, SubpageId};
|
||||
use msg::constellation_msg::{LoadData, WindowSizeData};
|
||||
use msg::constellation_msg::{PipelineNamespaceId};
|
||||
use net_traits::ResourceThread;
|
||||
|
@ -85,8 +84,8 @@ pub struct InitialPipelineState {
|
|||
pub constellation_chan: ConstellationChan<ScriptMsg>,
|
||||
/// A channel for the layout thread to send messages to the constellation.
|
||||
pub layout_to_constellation_chan: ConstellationChan<LayoutMsg>,
|
||||
/// A channel to the associated paint thread.
|
||||
pub painter_chan: ConstellationChan<PaintMsg>,
|
||||
/// A channel to report panics
|
||||
pub panic_chan: ConstellationChan<PanicMsg>,
|
||||
/// A channel to schedule timer events.
|
||||
pub scheduler_chan: IpcSender<TimerEventRequest>,
|
||||
/// A channel to the compositor.
|
||||
|
@ -140,8 +139,6 @@ impl Pipeline {
|
|||
.expect("Pipeline script to compositor chan");
|
||||
let mut pipeline_port = Some(pipeline_port);
|
||||
|
||||
let failure = Failure::new(state.id, state.parent_info);
|
||||
|
||||
let window_size = state.window_size.map(|size| {
|
||||
WindowSizeData {
|
||||
visible_viewport: size,
|
||||
|
@ -179,7 +176,7 @@ impl Pipeline {
|
|||
subpage_id: subpage_id,
|
||||
load_data: state.load_data.clone(),
|
||||
paint_chan: layout_to_paint_chan.clone().to_opaque(),
|
||||
failure: failure.clone(),
|
||||
panic_chan: state.panic_chan.clone(),
|
||||
pipeline_port: mem::replace(&mut pipeline_port, None)
|
||||
.expect("script_pipeline != None but pipeline_port == None"),
|
||||
layout_shutdown_chan: layout_shutdown_chan.clone(),
|
||||
|
@ -227,7 +224,7 @@ impl Pipeline {
|
|||
layout_to_constellation_chan: state.layout_to_constellation_chan,
|
||||
script_chan: script_chan,
|
||||
load_data: state.load_data.clone(),
|
||||
failure: failure.clone(),
|
||||
panic_chan: state.panic_chan.clone(),
|
||||
script_port: script_port,
|
||||
opts: (*opts::get()).clone(),
|
||||
prefs: prefs::get_cloned(),
|
||||
|
@ -246,13 +243,12 @@ impl Pipeline {
|
|||
|
||||
let privileged_pipeline_content = PrivilegedPipelineContent {
|
||||
id: state.id,
|
||||
painter_chan: state.painter_chan,
|
||||
compositor_proxy: state.compositor_proxy,
|
||||
font_cache_thread: state.font_cache_thread,
|
||||
time_profiler_chan: state.time_profiler_chan,
|
||||
mem_profiler_chan: state.mem_profiler_chan,
|
||||
load_data: state.load_data,
|
||||
failure: failure,
|
||||
panic_chan: state.panic_chan,
|
||||
layout_to_paint_port: layout_to_paint_port,
|
||||
chrome_to_paint_chan: chrome_to_paint_chan,
|
||||
chrome_to_paint_port: chrome_to_paint_port,
|
||||
|
@ -403,7 +399,7 @@ pub struct UnprivilegedPipelineContent {
|
|||
window_size: Option<WindowSizeData>,
|
||||
script_chan: IpcSender<ConstellationControlMsg>,
|
||||
load_data: LoadData,
|
||||
failure: Failure,
|
||||
panic_chan: ConstellationChan<PanicMsg>,
|
||||
script_port: Option<IpcReceiver<ConstellationControlMsg>>,
|
||||
layout_to_paint_chan: OptionalIpcSender<LayoutToPaintMsg>,
|
||||
opts: Opts,
|
||||
|
@ -433,7 +429,7 @@ impl UnprivilegedPipelineContent {
|
|||
constellation_chan: self.constellation_chan.clone(),
|
||||
layout_to_constellation_chan: self.layout_to_constellation_chan.clone(),
|
||||
scheduler_chan: self.scheduler_chan.clone(),
|
||||
failure_info: self.failure.clone(),
|
||||
panic_chan: self.panic_chan.clone(),
|
||||
resource_thread: self.resource_thread,
|
||||
storage_thread: self.storage_thread.clone(),
|
||||
image_cache_thread: self.image_cache_thread.clone(),
|
||||
|
@ -452,7 +448,7 @@ impl UnprivilegedPipelineContent {
|
|||
layout_pair,
|
||||
self.pipeline_port.expect("No pipeline port."),
|
||||
self.layout_to_constellation_chan,
|
||||
self.failure,
|
||||
self.panic_chan,
|
||||
self.script_chan.clone(),
|
||||
self.layout_to_paint_chan.clone(),
|
||||
self.image_cache_thread,
|
||||
|
@ -480,14 +476,13 @@ impl UnprivilegedPipelineContent {
|
|||
|
||||
pub struct PrivilegedPipelineContent {
|
||||
id: PipelineId,
|
||||
painter_chan: ConstellationChan<PaintMsg>,
|
||||
compositor_proxy: Box<CompositorProxy + Send + 'static>,
|
||||
script_to_compositor_port: IpcReceiver<ScriptToCompositorMsg>,
|
||||
font_cache_thread: FontCacheThread,
|
||||
time_profiler_chan: time::ProfilerChan,
|
||||
mem_profiler_chan: profile_mem::ProfilerChan,
|
||||
load_data: LoadData,
|
||||
failure: Failure,
|
||||
panic_chan: ConstellationChan<PanicMsg>,
|
||||
layout_to_paint_port: Receiver<LayoutToPaintMsg>,
|
||||
chrome_to_paint_chan: Sender<ChromeToPaintMsg>,
|
||||
chrome_to_paint_port: Receiver<ChromeToPaintMsg>,
|
||||
|
@ -502,9 +497,8 @@ impl PrivilegedPipelineContent {
|
|||
self.layout_to_paint_port,
|
||||
self.chrome_to_paint_port,
|
||||
self.compositor_proxy.clone_compositor_proxy(),
|
||||
self.painter_chan,
|
||||
self.panic_chan,
|
||||
self.font_cache_thread,
|
||||
self.failure,
|
||||
self.time_profiler_chan,
|
||||
self.mem_profiler_chan,
|
||||
self.paint_shutdown_chan);
|
||||
|
@ -526,9 +520,8 @@ impl PrivilegedPipelineContent {
|
|||
self.layout_to_paint_port,
|
||||
self.chrome_to_paint_port,
|
||||
self.compositor_proxy,
|
||||
self.painter_chan,
|
||||
self.panic_chan,
|
||||
self.font_cache_thread,
|
||||
self.failure,
|
||||
self.time_profiler_chan,
|
||||
self.mem_profiler_chan,
|
||||
self.paint_shutdown_chan);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue