mirror of
https://github.com/servo/servo.git
synced 2025-07-23 15:23:42 +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"))]
|
#[cfg(not(target_os = "windows"))]
|
||||||
use gaol::sandbox::{self, Sandbox, SandboxMethods};
|
use gaol::sandbox::{self, Sandbox, SandboxMethods};
|
||||||
use gfx::font_cache_thread::FontCacheThread;
|
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::ipc::{self, IpcOneShotServer, IpcSender};
|
||||||
use ipc_channel::router::ROUTER;
|
use ipc_channel::router::ROUTER;
|
||||||
use layout_traits::{LayoutControlChan, LayoutThreadFactory};
|
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::{Key, KeyModifiers, KeyState, LoadData};
|
||||||
use msg::constellation_msg::{PipelineNamespace, PipelineNamespaceId, NavigationDirection};
|
use msg::constellation_msg::{PipelineNamespace, PipelineNamespaceId, NavigationDirection};
|
||||||
use msg::constellation_msg::{SubpageId, WindowSizeData};
|
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 msg::webdriver_msg;
|
||||||
use net_traits::image_cache_thread::ImageCacheThread;
|
use net_traits::image_cache_thread::ImageCacheThread;
|
||||||
use net_traits::storage_thread::{StorageThread, StorageThreadMsg};
|
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.
|
/// A channel through which layout thread messages can be sent to this object.
|
||||||
pub layout_sender: ConstellationChan<FromLayoutMsg>,
|
pub layout_sender: ConstellationChan<FromLayoutMsg>,
|
||||||
|
|
||||||
/// A channel through which paint thread messages can be sent to this object.
|
/// A channel through which panic messages can be sent to this object.
|
||||||
pub painter_sender: ConstellationChan<FromPaintMsg>,
|
pub panic_sender: ConstellationChan<PanicMsg>,
|
||||||
|
|
||||||
/// Receives messages from scripts.
|
/// Receives messages from scripts.
|
||||||
pub script_receiver: Receiver<FromScriptMsg>,
|
pub script_receiver: Receiver<FromScriptMsg>,
|
||||||
|
@ -107,8 +107,8 @@ pub struct Constellation<LTF, STF> {
|
||||||
/// Receives messages from the layout thread
|
/// Receives messages from the layout thread
|
||||||
pub layout_receiver: Receiver<FromLayoutMsg>,
|
pub layout_receiver: Receiver<FromLayoutMsg>,
|
||||||
|
|
||||||
/// Receives messages from paint thread.
|
/// Receives panic messages.
|
||||||
pub painter_receiver: Receiver<FromPaintMsg>,
|
pub panic_receiver: Receiver<PanicMsg>,
|
||||||
|
|
||||||
/// A channel (the implementation of which is port-specific) through which messages can be sent
|
/// A channel (the implementation of which is port-specific) through which messages can be sent
|
||||||
/// to the compositor.
|
/// to the compositor.
|
||||||
|
@ -320,19 +320,19 @@ impl<LTF: LayoutThreadFactory, STF: ScriptThreadFactory> Constellation<LTF, STF>
|
||||||
let (compositor_sender, compositor_receiver) = channel();
|
let (compositor_sender, compositor_receiver) = channel();
|
||||||
let (ipc_layout_receiver, ipc_layout_sender) = ConstellationChan::<FromLayoutMsg>::new();
|
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 layout_receiver = ROUTER.route_ipc_receiver_to_new_mpsc_receiver(ipc_layout_receiver);
|
||||||
let (ipc_painter_receiver, ipc_painter_sender) = ConstellationChan::<FromPaintMsg>::new();
|
let (ipc_panic_receiver, ipc_panic_sender) = ConstellationChan::<PanicMsg>::new();
|
||||||
let painter_receiver = ROUTER.route_ipc_receiver_to_new_mpsc_receiver(ipc_painter_receiver);
|
let panic_receiver = ROUTER.route_ipc_receiver_to_new_mpsc_receiver(ipc_panic_receiver);
|
||||||
let compositor_sender_clone = compositor_sender.clone();
|
let compositor_sender_clone = compositor_sender.clone();
|
||||||
spawn_named("Constellation".to_owned(), move || {
|
spawn_named("Constellation".to_owned(), move || {
|
||||||
let mut constellation: Constellation<LTF, STF> = Constellation {
|
let mut constellation: Constellation<LTF, STF> = Constellation {
|
||||||
script_sender: ipc_script_sender,
|
script_sender: ipc_script_sender,
|
||||||
compositor_sender: compositor_sender_clone,
|
compositor_sender: compositor_sender_clone,
|
||||||
layout_sender: ipc_layout_sender,
|
layout_sender: ipc_layout_sender,
|
||||||
painter_sender: ipc_painter_sender,
|
|
||||||
script_receiver: script_receiver,
|
script_receiver: script_receiver,
|
||||||
|
panic_sender: ipc_panic_sender,
|
||||||
compositor_receiver: compositor_receiver,
|
compositor_receiver: compositor_receiver,
|
||||||
layout_receiver: layout_receiver,
|
layout_receiver: layout_receiver,
|
||||||
painter_receiver: painter_receiver,
|
panic_receiver: panic_receiver,
|
||||||
compositor_proxy: state.compositor_proxy,
|
compositor_proxy: state.compositor_proxy,
|
||||||
devtools_chan: state.devtools_chan,
|
devtools_chan: state.devtools_chan,
|
||||||
resource_thread: state.resource_thread,
|
resource_thread: state.resource_thread,
|
||||||
|
@ -416,7 +416,7 @@ impl<LTF: LayoutThreadFactory, STF: ScriptThreadFactory> Constellation<LTF, STF>
|
||||||
parent_info: parent_info,
|
parent_info: parent_info,
|
||||||
constellation_chan: self.script_sender.clone(),
|
constellation_chan: self.script_sender.clone(),
|
||||||
layout_to_constellation_chan: self.layout_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(),
|
scheduler_chan: self.scheduler_chan.clone(),
|
||||||
compositor_proxy: self.compositor_proxy.clone_compositor_proxy(),
|
compositor_proxy: self.compositor_proxy.clone_compositor_proxy(),
|
||||||
devtools_chan: self.devtools_chan.clone(),
|
devtools_chan: self.devtools_chan.clone(),
|
||||||
|
@ -548,7 +548,7 @@ impl<LTF: LayoutThreadFactory, STF: ScriptThreadFactory> Constellation<LTF, STF>
|
||||||
Script(FromScriptMsg),
|
Script(FromScriptMsg),
|
||||||
Compositor(FromCompositorMsg),
|
Compositor(FromCompositorMsg),
|
||||||
Layout(FromLayoutMsg),
|
Layout(FromLayoutMsg),
|
||||||
Paint(FromPaintMsg)
|
Panic(PanicMsg)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get one incoming request.
|
// 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_script = &self.script_receiver;
|
||||||
let receiver_from_compositor = &self.compositor_receiver;
|
let receiver_from_compositor = &self.compositor_receiver;
|
||||||
let receiver_from_layout = &self.layout_receiver;
|
let receiver_from_layout = &self.layout_receiver;
|
||||||
let receiver_from_paint = &self.painter_receiver;
|
let receiver_from_panic = &self.panic_receiver;
|
||||||
select! {
|
select! {
|
||||||
msg = receiver_from_script.recv() =>
|
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() =>
|
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() =>
|
msg = receiver_from_layout.recv() =>
|
||||||
Request::Layout(msg.expect("Unexpected layout failure in constellation")),
|
Request::Layout(msg.expect("Unexpected layout channel panic in constellation")),
|
||||||
msg = receiver_from_paint.recv() =>
|
msg = receiver_from_panic.recv() =>
|
||||||
Request::Paint(msg.expect("Unexpected paint failure in constellation"))
|
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
|
// 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)) => {
|
Request::Script(FromScriptMsg::ScriptLoadedURLInIFrame(load_info)) => {
|
||||||
debug!("constellation got iframe URL load message {:?} {:?} {:?}",
|
debug!("constellation got iframe URL load message {:?} {:?} {:?}",
|
||||||
load_info.containing_pipeline_id,
|
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)) => {
|
Request::Layout(FromLayoutMsg::ChangeRunningAnimationsState(pipeline_id, animation_state)) => {
|
||||||
self.handle_change_running_animations_state(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)) => {
|
Request::Layout(FromLayoutMsg::SetCursor(cursor)) => {
|
||||||
self.handle_set_cursor_msg(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
|
||||||
|
|
||||||
|
Request::Panic((pipeline_id, panic_reason)) => {
|
||||||
// Notification that painting has finished and is requesting permission to paint.
|
debug!("handling panic message ({:?})", pipeline_id);
|
||||||
Request::Paint(FromPaintMsg::Failure(failure)) => {
|
self.handle_panic(pipeline_id, panic_reason);
|
||||||
debug!("handling paint failure message from pipeline {:?}", failure);
|
|
||||||
self.handle_failure_msg(failure);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
@ -851,17 +840,12 @@ impl<LTF: LayoutThreadFactory, STF: ScriptThreadFactory> Constellation<LTF, STF>
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_send_error(&mut self, pipeline_id: PipelineId, err: IOError) {
|
fn handle_send_error(&mut self, pipeline_id: PipelineId, err: IOError) {
|
||||||
let parent_info = match self.pipelines.get(&pipeline_id) {
|
// Treat send error the same as receiving a panic message
|
||||||
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
|
|
||||||
debug!("Pipeline {:?} send error ({}).", pipeline_id, err);
|
debug!("Pipeline {:?} send error ({}).", pipeline_id, err);
|
||||||
let failure = Failure::new(pipeline_id, parent_info);
|
self.handle_panic(Some(pipeline_id), format!("Send failed ({})", err));
|
||||||
self.handle_failure_msg(failure);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_failure_msg(&mut self, failure: Failure) {
|
fn handle_panic(&mut self, pipeline_id: Option<PipelineId>, reason: String) {
|
||||||
if opts::get().hard_fail {
|
if opts::get().hard_fail {
|
||||||
// It's quite difficult to make Servo exit cleanly if some threads have failed.
|
// 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.
|
// 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);
|
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
|
// 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| {
|
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) {
|
}).map(|frame| frame.new_pipeline_id) {
|
||||||
warn!("removing pending frame change for failed pipeline");
|
warn!("removing pending frame change for failed pipeline");
|
||||||
self.close_pipeline(pending_pipeline_id, ExitPipelineMode::Force);
|
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();
|
let new_pipeline_id = PipelineId::new();
|
||||||
self.new_pipeline(new_pipeline_id,
|
self.new_pipeline(new_pipeline_id,
|
||||||
failure.parent_info,
|
parent_info,
|
||||||
window_size,
|
window_size,
|
||||||
None,
|
None,
|
||||||
LoadData::new(Url::parse("about:failure").expect("infallible")));
|
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 euclid::size::TypedSize2D;
|
||||||
use gfx::font_cache_thread::FontCacheThread;
|
use gfx::font_cache_thread::FontCacheThread;
|
||||||
use gfx::paint_thread::{ChromeToPaintMsg, LayoutToPaintMsg, PaintThread};
|
use gfx::paint_thread::{ChromeToPaintMsg, LayoutToPaintMsg, PaintThread};
|
||||||
use gfx_traits::PaintMsg;
|
|
||||||
use ipc_channel::ipc::{self, IpcReceiver, IpcSender};
|
use ipc_channel::ipc::{self, IpcReceiver, IpcSender};
|
||||||
use ipc_channel::router::ROUTER;
|
use ipc_channel::router::ROUTER;
|
||||||
use layers::geometry::DevicePixel;
|
use layers::geometry::DevicePixel;
|
||||||
use layout_traits::{LayoutControlChan, LayoutThreadFactory};
|
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::{LoadData, WindowSizeData};
|
||||||
use msg::constellation_msg::{PipelineNamespaceId};
|
use msg::constellation_msg::{PipelineNamespaceId};
|
||||||
use net_traits::ResourceThread;
|
use net_traits::ResourceThread;
|
||||||
|
@ -85,8 +84,8 @@ pub struct InitialPipelineState {
|
||||||
pub constellation_chan: ConstellationChan<ScriptMsg>,
|
pub constellation_chan: ConstellationChan<ScriptMsg>,
|
||||||
/// A channel for the layout thread to send messages to the constellation.
|
/// A channel for the layout thread to send messages to the constellation.
|
||||||
pub layout_to_constellation_chan: ConstellationChan<LayoutMsg>,
|
pub layout_to_constellation_chan: ConstellationChan<LayoutMsg>,
|
||||||
/// A channel to the associated paint thread.
|
/// A channel to report panics
|
||||||
pub painter_chan: ConstellationChan<PaintMsg>,
|
pub panic_chan: ConstellationChan<PanicMsg>,
|
||||||
/// A channel to schedule timer events.
|
/// A channel to schedule timer events.
|
||||||
pub scheduler_chan: IpcSender<TimerEventRequest>,
|
pub scheduler_chan: IpcSender<TimerEventRequest>,
|
||||||
/// A channel to the compositor.
|
/// A channel to the compositor.
|
||||||
|
@ -140,8 +139,6 @@ impl Pipeline {
|
||||||
.expect("Pipeline script to compositor chan");
|
.expect("Pipeline script to compositor chan");
|
||||||
let mut pipeline_port = Some(pipeline_port);
|
let mut pipeline_port = Some(pipeline_port);
|
||||||
|
|
||||||
let failure = Failure::new(state.id, state.parent_info);
|
|
||||||
|
|
||||||
let window_size = state.window_size.map(|size| {
|
let window_size = state.window_size.map(|size| {
|
||||||
WindowSizeData {
|
WindowSizeData {
|
||||||
visible_viewport: size,
|
visible_viewport: size,
|
||||||
|
@ -179,7 +176,7 @@ impl Pipeline {
|
||||||
subpage_id: subpage_id,
|
subpage_id: subpage_id,
|
||||||
load_data: state.load_data.clone(),
|
load_data: state.load_data.clone(),
|
||||||
paint_chan: layout_to_paint_chan.clone().to_opaque(),
|
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)
|
pipeline_port: mem::replace(&mut pipeline_port, None)
|
||||||
.expect("script_pipeline != None but pipeline_port == None"),
|
.expect("script_pipeline != None but pipeline_port == None"),
|
||||||
layout_shutdown_chan: layout_shutdown_chan.clone(),
|
layout_shutdown_chan: layout_shutdown_chan.clone(),
|
||||||
|
@ -227,7 +224,7 @@ impl Pipeline {
|
||||||
layout_to_constellation_chan: state.layout_to_constellation_chan,
|
layout_to_constellation_chan: state.layout_to_constellation_chan,
|
||||||
script_chan: script_chan,
|
script_chan: script_chan,
|
||||||
load_data: state.load_data.clone(),
|
load_data: state.load_data.clone(),
|
||||||
failure: failure.clone(),
|
panic_chan: state.panic_chan.clone(),
|
||||||
script_port: script_port,
|
script_port: script_port,
|
||||||
opts: (*opts::get()).clone(),
|
opts: (*opts::get()).clone(),
|
||||||
prefs: prefs::get_cloned(),
|
prefs: prefs::get_cloned(),
|
||||||
|
@ -246,13 +243,12 @@ impl Pipeline {
|
||||||
|
|
||||||
let privileged_pipeline_content = PrivilegedPipelineContent {
|
let privileged_pipeline_content = PrivilegedPipelineContent {
|
||||||
id: state.id,
|
id: state.id,
|
||||||
painter_chan: state.painter_chan,
|
|
||||||
compositor_proxy: state.compositor_proxy,
|
compositor_proxy: state.compositor_proxy,
|
||||||
font_cache_thread: state.font_cache_thread,
|
font_cache_thread: state.font_cache_thread,
|
||||||
time_profiler_chan: state.time_profiler_chan,
|
time_profiler_chan: state.time_profiler_chan,
|
||||||
mem_profiler_chan: state.mem_profiler_chan,
|
mem_profiler_chan: state.mem_profiler_chan,
|
||||||
load_data: state.load_data,
|
load_data: state.load_data,
|
||||||
failure: failure,
|
panic_chan: state.panic_chan,
|
||||||
layout_to_paint_port: layout_to_paint_port,
|
layout_to_paint_port: layout_to_paint_port,
|
||||||
chrome_to_paint_chan: chrome_to_paint_chan,
|
chrome_to_paint_chan: chrome_to_paint_chan,
|
||||||
chrome_to_paint_port: chrome_to_paint_port,
|
chrome_to_paint_port: chrome_to_paint_port,
|
||||||
|
@ -403,7 +399,7 @@ pub struct UnprivilegedPipelineContent {
|
||||||
window_size: Option<WindowSizeData>,
|
window_size: Option<WindowSizeData>,
|
||||||
script_chan: IpcSender<ConstellationControlMsg>,
|
script_chan: IpcSender<ConstellationControlMsg>,
|
||||||
load_data: LoadData,
|
load_data: LoadData,
|
||||||
failure: Failure,
|
panic_chan: ConstellationChan<PanicMsg>,
|
||||||
script_port: Option<IpcReceiver<ConstellationControlMsg>>,
|
script_port: Option<IpcReceiver<ConstellationControlMsg>>,
|
||||||
layout_to_paint_chan: OptionalIpcSender<LayoutToPaintMsg>,
|
layout_to_paint_chan: OptionalIpcSender<LayoutToPaintMsg>,
|
||||||
opts: Opts,
|
opts: Opts,
|
||||||
|
@ -433,7 +429,7 @@ impl UnprivilegedPipelineContent {
|
||||||
constellation_chan: self.constellation_chan.clone(),
|
constellation_chan: self.constellation_chan.clone(),
|
||||||
layout_to_constellation_chan: self.layout_to_constellation_chan.clone(),
|
layout_to_constellation_chan: self.layout_to_constellation_chan.clone(),
|
||||||
scheduler_chan: self.scheduler_chan.clone(),
|
scheduler_chan: self.scheduler_chan.clone(),
|
||||||
failure_info: self.failure.clone(),
|
panic_chan: self.panic_chan.clone(),
|
||||||
resource_thread: self.resource_thread,
|
resource_thread: self.resource_thread,
|
||||||
storage_thread: self.storage_thread.clone(),
|
storage_thread: self.storage_thread.clone(),
|
||||||
image_cache_thread: self.image_cache_thread.clone(),
|
image_cache_thread: self.image_cache_thread.clone(),
|
||||||
|
@ -452,7 +448,7 @@ impl UnprivilegedPipelineContent {
|
||||||
layout_pair,
|
layout_pair,
|
||||||
self.pipeline_port.expect("No pipeline port."),
|
self.pipeline_port.expect("No pipeline port."),
|
||||||
self.layout_to_constellation_chan,
|
self.layout_to_constellation_chan,
|
||||||
self.failure,
|
self.panic_chan,
|
||||||
self.script_chan.clone(),
|
self.script_chan.clone(),
|
||||||
self.layout_to_paint_chan.clone(),
|
self.layout_to_paint_chan.clone(),
|
||||||
self.image_cache_thread,
|
self.image_cache_thread,
|
||||||
|
@ -480,14 +476,13 @@ impl UnprivilegedPipelineContent {
|
||||||
|
|
||||||
pub struct PrivilegedPipelineContent {
|
pub struct PrivilegedPipelineContent {
|
||||||
id: PipelineId,
|
id: PipelineId,
|
||||||
painter_chan: ConstellationChan<PaintMsg>,
|
|
||||||
compositor_proxy: Box<CompositorProxy + Send + 'static>,
|
compositor_proxy: Box<CompositorProxy + Send + 'static>,
|
||||||
script_to_compositor_port: IpcReceiver<ScriptToCompositorMsg>,
|
script_to_compositor_port: IpcReceiver<ScriptToCompositorMsg>,
|
||||||
font_cache_thread: FontCacheThread,
|
font_cache_thread: FontCacheThread,
|
||||||
time_profiler_chan: time::ProfilerChan,
|
time_profiler_chan: time::ProfilerChan,
|
||||||
mem_profiler_chan: profile_mem::ProfilerChan,
|
mem_profiler_chan: profile_mem::ProfilerChan,
|
||||||
load_data: LoadData,
|
load_data: LoadData,
|
||||||
failure: Failure,
|
panic_chan: ConstellationChan<PanicMsg>,
|
||||||
layout_to_paint_port: Receiver<LayoutToPaintMsg>,
|
layout_to_paint_port: Receiver<LayoutToPaintMsg>,
|
||||||
chrome_to_paint_chan: Sender<ChromeToPaintMsg>,
|
chrome_to_paint_chan: Sender<ChromeToPaintMsg>,
|
||||||
chrome_to_paint_port: Receiver<ChromeToPaintMsg>,
|
chrome_to_paint_port: Receiver<ChromeToPaintMsg>,
|
||||||
|
@ -502,9 +497,8 @@ impl PrivilegedPipelineContent {
|
||||||
self.layout_to_paint_port,
|
self.layout_to_paint_port,
|
||||||
self.chrome_to_paint_port,
|
self.chrome_to_paint_port,
|
||||||
self.compositor_proxy.clone_compositor_proxy(),
|
self.compositor_proxy.clone_compositor_proxy(),
|
||||||
self.painter_chan,
|
self.panic_chan,
|
||||||
self.font_cache_thread,
|
self.font_cache_thread,
|
||||||
self.failure,
|
|
||||||
self.time_profiler_chan,
|
self.time_profiler_chan,
|
||||||
self.mem_profiler_chan,
|
self.mem_profiler_chan,
|
||||||
self.paint_shutdown_chan);
|
self.paint_shutdown_chan);
|
||||||
|
@ -526,9 +520,8 @@ impl PrivilegedPipelineContent {
|
||||||
self.layout_to_paint_port,
|
self.layout_to_paint_port,
|
||||||
self.chrome_to_paint_port,
|
self.chrome_to_paint_port,
|
||||||
self.compositor_proxy,
|
self.compositor_proxy,
|
||||||
self.painter_chan,
|
self.panic_chan,
|
||||||
self.font_cache_thread,
|
self.font_cache_thread,
|
||||||
self.failure,
|
|
||||||
self.time_profiler_chan,
|
self.time_profiler_chan,
|
||||||
self.mem_profiler_chan,
|
self.mem_profiler_chan,
|
||||||
self.paint_shutdown_chan);
|
self.paint_shutdown_chan);
|
||||||
|
|
|
@ -15,12 +15,11 @@ use euclid::rect::Rect;
|
||||||
use euclid::size::Size2D;
|
use euclid::size::Size2D;
|
||||||
use font_cache_thread::FontCacheThread;
|
use font_cache_thread::FontCacheThread;
|
||||||
use font_context::FontContext;
|
use font_context::FontContext;
|
||||||
use gfx_traits::PaintMsg as ConstellationMsg;
|
|
||||||
use gfx_traits::{Epoch, FrameTreeId, LayerId, LayerKind, LayerProperties, PaintListener};
|
use gfx_traits::{Epoch, FrameTreeId, LayerId, LayerKind, LayerProperties, PaintListener};
|
||||||
use ipc_channel::ipc::IpcSender;
|
use ipc_channel::ipc::IpcSender;
|
||||||
use layers::layers::{BufferRequest, LayerBuffer, LayerBufferSet};
|
use layers::layers::{BufferRequest, LayerBuffer, LayerBufferSet};
|
||||||
use layers::platform::surface::{NativeDisplay, NativeSurface};
|
use layers::platform::surface::{NativeDisplay, NativeSurface};
|
||||||
use msg::constellation_msg::{ConstellationChan, Failure, PipelineId};
|
use msg::constellation_msg::{ConstellationChan, PanicMsg, PipelineId};
|
||||||
use paint_context::PaintContext;
|
use paint_context::PaintContext;
|
||||||
use profile_traits::mem::{self, ReportsChan};
|
use profile_traits::mem::{self, ReportsChan};
|
||||||
use profile_traits::time;
|
use profile_traits::time;
|
||||||
|
@ -394,14 +393,13 @@ impl<C> PaintThread<C> where C: PaintListener + Send + 'static {
|
||||||
layout_to_paint_port: Receiver<LayoutToPaintMsg>,
|
layout_to_paint_port: Receiver<LayoutToPaintMsg>,
|
||||||
chrome_to_paint_port: Receiver<ChromeToPaintMsg>,
|
chrome_to_paint_port: Receiver<ChromeToPaintMsg>,
|
||||||
compositor: C,
|
compositor: C,
|
||||||
constellation_chan: ConstellationChan<ConstellationMsg>,
|
panic_chan: ConstellationChan<PanicMsg>,
|
||||||
font_cache_thread: FontCacheThread,
|
font_cache_thread: FontCacheThread,
|
||||||
failure_msg: Failure,
|
|
||||||
time_profiler_chan: time::ProfilerChan,
|
time_profiler_chan: time::ProfilerChan,
|
||||||
mem_profiler_chan: mem::ProfilerChan,
|
mem_profiler_chan: mem::ProfilerChan,
|
||||||
shutdown_chan: IpcSender<()>) {
|
shutdown_chan: IpcSender<()>) {
|
||||||
let ConstellationChan(c) = constellation_chan.clone();
|
let ConstellationChan(c) = panic_chan.clone();
|
||||||
thread::spawn_named_with_send_on_failure(format!("PaintThread {:?}", id),
|
thread::spawn_named_with_send_on_panic(format!("PaintThread {:?}", id),
|
||||||
thread_state::PAINT,
|
thread_state::PAINT,
|
||||||
move || {
|
move || {
|
||||||
{
|
{
|
||||||
|
@ -441,7 +439,7 @@ impl<C> PaintThread<C> where C: PaintListener + Send + 'static {
|
||||||
|
|
||||||
debug!("paint_thread: shutdown_chan send");
|
debug!("paint_thread: shutdown_chan send");
|
||||||
shutdown_chan.send(()).unwrap();
|
shutdown_chan.send(()).unwrap();
|
||||||
}, failure_msg, c);
|
}, Some(id), c);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(unsafe_code)]
|
#[allow(unsafe_code)]
|
||||||
|
|
|
@ -25,21 +25,9 @@ pub use paint_listener::PaintListener;
|
||||||
use azure::azure_hl::Color;
|
use azure::azure_hl::Color;
|
||||||
use euclid::Matrix4D;
|
use euclid::Matrix4D;
|
||||||
use euclid::rect::Rect;
|
use euclid::rect::Rect;
|
||||||
use msg::constellation_msg::{Failure, PipelineId};
|
use msg::constellation_msg::{PipelineId};
|
||||||
use std::fmt::{self, Debug, Formatter};
|
use std::fmt::{self, Debug, Formatter};
|
||||||
|
|
||||||
/// Messages from the paint task to the constellation.
|
|
||||||
#[derive(Deserialize, Serialize)]
|
|
||||||
pub enum PaintMsg {
|
|
||||||
Failure(Failure),
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<Failure> for PaintMsg {
|
|
||||||
fn from(failure: Failure) -> PaintMsg {
|
|
||||||
PaintMsg::Failure(failure)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug, PartialEq)]
|
#[derive(Clone, Copy, Debug, PartialEq)]
|
||||||
pub enum LayerKind {
|
pub enum LayerKind {
|
||||||
NoTransform,
|
NoTransform,
|
||||||
|
|
|
@ -37,7 +37,7 @@ use ipc_channel::router::ROUTER;
|
||||||
use layout_debug;
|
use layout_debug;
|
||||||
use layout_traits::LayoutThreadFactory;
|
use layout_traits::LayoutThreadFactory;
|
||||||
use log;
|
use log;
|
||||||
use msg::constellation_msg::{ConstellationChan, ConvertPipelineIdToWebRender, Failure, PipelineId};
|
use msg::constellation_msg::{ConstellationChan, ConvertPipelineIdToWebRender, PanicMsg, PipelineId};
|
||||||
use net_traits::image_cache_thread::{ImageCacheChan, ImageCacheResult, ImageCacheThread};
|
use net_traits::image_cache_thread::{ImageCacheChan, ImageCacheResult, ImageCacheThread};
|
||||||
use net_traits::image_cache_thread::{UsePlaceholder};
|
use net_traits::image_cache_thread::{UsePlaceholder};
|
||||||
use parallel;
|
use parallel;
|
||||||
|
@ -249,7 +249,7 @@ impl LayoutThreadFactory for LayoutThread {
|
||||||
chan: OpaqueScriptLayoutChannel,
|
chan: OpaqueScriptLayoutChannel,
|
||||||
pipeline_port: IpcReceiver<LayoutControlMsg>,
|
pipeline_port: IpcReceiver<LayoutControlMsg>,
|
||||||
constellation_chan: ConstellationChan<ConstellationMsg>,
|
constellation_chan: ConstellationChan<ConstellationMsg>,
|
||||||
failure_msg: Failure,
|
panic_chan: ConstellationChan<PanicMsg>,
|
||||||
script_chan: IpcSender<ConstellationControlMsg>,
|
script_chan: IpcSender<ConstellationControlMsg>,
|
||||||
paint_chan: OptionalIpcSender<LayoutToPaintMsg>,
|
paint_chan: OptionalIpcSender<LayoutToPaintMsg>,
|
||||||
image_cache_thread: ImageCacheThread,
|
image_cache_thread: ImageCacheThread,
|
||||||
|
@ -259,8 +259,8 @@ impl LayoutThreadFactory for LayoutThread {
|
||||||
shutdown_chan: IpcSender<()>,
|
shutdown_chan: IpcSender<()>,
|
||||||
content_process_shutdown_chan: IpcSender<()>,
|
content_process_shutdown_chan: IpcSender<()>,
|
||||||
webrender_api_sender: Option<webrender_traits::RenderApiSender>) {
|
webrender_api_sender: Option<webrender_traits::RenderApiSender>) {
|
||||||
let ConstellationChan(con_chan) = constellation_chan.clone();
|
let ConstellationChan(fail_chan) = panic_chan.clone();
|
||||||
thread::spawn_named_with_send_on_failure(format!("LayoutThread {:?}", id),
|
thread::spawn_named_with_send_on_panic(format!("LayoutThread {:?}", id),
|
||||||
thread_state::LAYOUT,
|
thread_state::LAYOUT,
|
||||||
move || {
|
move || {
|
||||||
{ // Ensures layout thread is destroyed before we send shutdown message
|
{ // Ensures layout thread is destroyed before we send shutdown message
|
||||||
|
@ -286,7 +286,7 @@ impl LayoutThreadFactory for LayoutThread {
|
||||||
}
|
}
|
||||||
let _ = shutdown_chan.send(());
|
let _ = shutdown_chan.send(());
|
||||||
let _ = content_process_shutdown_chan.send(());
|
let _ = content_process_shutdown_chan.send(());
|
||||||
}, failure_msg, con_chan);
|
}, Some(id), fail_chan);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -732,7 +732,7 @@ impl LayoutThread {
|
||||||
info.layout_pair,
|
info.layout_pair,
|
||||||
info.pipeline_port,
|
info.pipeline_port,
|
||||||
info.constellation_chan,
|
info.constellation_chan,
|
||||||
info.failure,
|
info.panic_chan,
|
||||||
info.script_chan.clone(),
|
info.script_chan.clone(),
|
||||||
info.paint_chan.to::<LayoutToPaintMsg>(),
|
info.paint_chan.to::<LayoutToPaintMsg>(),
|
||||||
self.image_cache_thread.clone(),
|
self.image_cache_thread.clone(),
|
||||||
|
|
|
@ -26,7 +26,7 @@ extern crate webrender_traits;
|
||||||
use gfx::font_cache_thread::FontCacheThread;
|
use gfx::font_cache_thread::FontCacheThread;
|
||||||
use gfx::paint_thread::LayoutToPaintMsg;
|
use gfx::paint_thread::LayoutToPaintMsg;
|
||||||
use ipc_channel::ipc::{IpcReceiver, IpcSender};
|
use ipc_channel::ipc::{IpcReceiver, IpcSender};
|
||||||
use msg::constellation_msg::{ConstellationChan, Failure, PipelineId};
|
use msg::constellation_msg::{ConstellationChan, PanicMsg, PipelineId};
|
||||||
use net_traits::image_cache_thread::ImageCacheThread;
|
use net_traits::image_cache_thread::ImageCacheThread;
|
||||||
use profile_traits::{mem, time};
|
use profile_traits::{mem, time};
|
||||||
use script_traits::LayoutMsg as ConstellationMsg;
|
use script_traits::LayoutMsg as ConstellationMsg;
|
||||||
|
@ -49,7 +49,7 @@ pub trait LayoutThreadFactory {
|
||||||
chan: OpaqueScriptLayoutChannel,
|
chan: OpaqueScriptLayoutChannel,
|
||||||
pipeline_port: IpcReceiver<LayoutControlMsg>,
|
pipeline_port: IpcReceiver<LayoutControlMsg>,
|
||||||
constellation_chan: ConstellationChan<ConstellationMsg>,
|
constellation_chan: ConstellationChan<ConstellationMsg>,
|
||||||
failure_msg: Failure,
|
panic_chan: ConstellationChan<PanicMsg>,
|
||||||
script_chan: IpcSender<ConstellationControlMsg>,
|
script_chan: IpcSender<ConstellationControlMsg>,
|
||||||
layout_to_paint_chan: OptionalIpcSender<LayoutToPaintMsg>,
|
layout_to_paint_chan: OptionalIpcSender<LayoutToPaintMsg>,
|
||||||
image_cache_thread: ImageCacheThread,
|
image_cache_thread: ImageCacheThread,
|
||||||
|
|
|
@ -16,7 +16,6 @@ use std::cell::Cell;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use url::Url;
|
use url::Url;
|
||||||
use util::geometry::{PagePx, ViewportPx};
|
use util::geometry::{PagePx, ViewportPx};
|
||||||
use util::thread::AddFailureDetails;
|
|
||||||
use webdriver_msg::{LoadStatus, WebDriverScriptCommand};
|
use webdriver_msg::{LoadStatus, WebDriverScriptCommand};
|
||||||
use webrender_traits;
|
use webrender_traits;
|
||||||
|
|
||||||
|
@ -36,29 +35,7 @@ impl<T: Serialize + Deserialize> Clone for ConstellationChan<T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// We pass this info to various threads, so it lives in a separate, cloneable struct.
|
pub type PanicMsg = (Option<PipelineId>, String);
|
||||||
#[derive(Clone, Deserialize, Serialize, Debug)]
|
|
||||||
pub struct Failure {
|
|
||||||
pub pipeline_id: PipelineId,
|
|
||||||
pub parent_info: Option<(PipelineId, SubpageId)>,
|
|
||||||
pub panic_message: Option<String>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Failure {
|
|
||||||
pub fn new(pipeline_id: PipelineId, parent_info: Option<(PipelineId, SubpageId)>) -> Failure {
|
|
||||||
Failure {
|
|
||||||
pipeline_id: pipeline_id,
|
|
||||||
parent_info: parent_info,
|
|
||||||
panic_message: None,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl AddFailureDetails for Failure {
|
|
||||||
fn add_panic_message(&mut self, message: String) {
|
|
||||||
self.panic_message = Some(message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Copy, Clone, Deserialize, Serialize, HeapSizeOf)]
|
#[derive(Copy, Clone, Deserialize, Serialize, HeapSizeOf)]
|
||||||
pub struct WindowSizeData {
|
pub struct WindowSizeData {
|
||||||
|
|
|
@ -12,7 +12,7 @@ use euclid::point::Point2D;
|
||||||
use euclid::rect::Rect;
|
use euclid::rect::Rect;
|
||||||
use gfx_traits::{Epoch, LayerId};
|
use gfx_traits::{Epoch, LayerId};
|
||||||
use ipc_channel::ipc::{IpcReceiver, IpcSender};
|
use ipc_channel::ipc::{IpcReceiver, IpcSender};
|
||||||
use msg::constellation_msg::{ConstellationChan, Failure, PipelineId};
|
use msg::constellation_msg::{ConstellationChan, PanicMsg, PipelineId};
|
||||||
use msg::constellation_msg::{WindowSizeData};
|
use msg::constellation_msg::{WindowSizeData};
|
||||||
use net_traits::image_cache_thread::ImageCacheThread;
|
use net_traits::image_cache_thread::ImageCacheThread;
|
||||||
use profile_traits::mem::ReportsChan;
|
use profile_traits::mem::ReportsChan;
|
||||||
|
@ -250,7 +250,7 @@ pub struct NewLayoutThreadInfo {
|
||||||
pub layout_pair: OpaqueScriptLayoutChannel,
|
pub layout_pair: OpaqueScriptLayoutChannel,
|
||||||
pub pipeline_port: IpcReceiver<LayoutControlMsg>,
|
pub pipeline_port: IpcReceiver<LayoutControlMsg>,
|
||||||
pub constellation_chan: ConstellationChan<ConstellationMsg>,
|
pub constellation_chan: ConstellationChan<ConstellationMsg>,
|
||||||
pub failure: Failure,
|
pub panic_chan: ConstellationChan<PanicMsg>,
|
||||||
pub script_chan: IpcSender<ConstellationControlMsg>,
|
pub script_chan: IpcSender<ConstellationControlMsg>,
|
||||||
pub image_cache_thread: ImageCacheThread,
|
pub image_cache_thread: ImageCacheThread,
|
||||||
pub paint_chan: OptionalOpaqueIpcSender,
|
pub paint_chan: OptionalOpaqueIpcSender,
|
||||||
|
|
|
@ -389,7 +389,7 @@ pub struct ScriptThread {
|
||||||
content_process_shutdown_chan: IpcSender<()>,
|
content_process_shutdown_chan: IpcSender<()>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// In the event of thread failure, all data on the stack runs its destructor. However, there
|
/// In the event of thread panic, all data on the stack runs its destructor. However, there
|
||||||
/// are no reachable, owning pointers to the DOM memory, so it never gets freed by default
|
/// are no reachable, owning pointers to the DOM memory, so it never gets freed by default
|
||||||
/// when the script thread fails. The ScriptMemoryFailsafe uses the destructor bomb pattern
|
/// when the script thread fails. The ScriptMemoryFailsafe uses the destructor bomb pattern
|
||||||
/// to forcibly tear down the JS compartments for pages associated with the failing ScriptThread.
|
/// to forcibly tear down the JS compartments for pages associated with the failing ScriptThread.
|
||||||
|
@ -442,11 +442,11 @@ impl ScriptThreadFactory for ScriptThread {
|
||||||
state: InitialScriptState,
|
state: InitialScriptState,
|
||||||
layout_chan: &OpaqueScriptLayoutChannel,
|
layout_chan: &OpaqueScriptLayoutChannel,
|
||||||
load_data: LoadData) {
|
load_data: LoadData) {
|
||||||
let ConstellationChan(const_chan) = state.constellation_chan.clone();
|
let ConstellationChan(panic_chan) = state.panic_chan.clone();
|
||||||
let (script_chan, script_port) = channel();
|
let (script_chan, script_port) = channel();
|
||||||
let layout_chan = LayoutChan(layout_chan.sender());
|
let layout_chan = LayoutChan(layout_chan.sender());
|
||||||
let failure_info = state.failure_info.clone();
|
let pipeline_id = state.id;
|
||||||
thread::spawn_named_with_send_on_failure(format!("ScriptThread {:?}", state.id),
|
thread::spawn_named_with_send_on_panic(format!("ScriptThread {:?}", state.id),
|
||||||
thread_state::SCRIPT,
|
thread_state::SCRIPT,
|
||||||
move || {
|
move || {
|
||||||
PipelineNamespace::install(state.pipeline_namespace_id);
|
PipelineNamespace::install(state.pipeline_namespace_id);
|
||||||
|
@ -481,7 +481,7 @@ impl ScriptThreadFactory for ScriptThread {
|
||||||
|
|
||||||
// This must always be the very last operation performed before the thread completes
|
// This must always be the very last operation performed before the thread completes
|
||||||
failsafe.neuter();
|
failsafe.neuter();
|
||||||
}, failure_info, const_chan);
|
}, Some(pipeline_id), panic_chan);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1061,7 +1061,7 @@ impl ScriptThread {
|
||||||
subpage_id,
|
subpage_id,
|
||||||
load_data,
|
load_data,
|
||||||
paint_chan,
|
paint_chan,
|
||||||
failure,
|
panic_chan,
|
||||||
pipeline_port,
|
pipeline_port,
|
||||||
layout_shutdown_chan,
|
layout_shutdown_chan,
|
||||||
content_process_shutdown_chan,
|
content_process_shutdown_chan,
|
||||||
|
@ -1079,7 +1079,7 @@ impl ScriptThread {
|
||||||
layout_pair: layout_pair,
|
layout_pair: layout_pair,
|
||||||
pipeline_port: pipeline_port,
|
pipeline_port: pipeline_port,
|
||||||
constellation_chan: self.layout_to_constellation_chan.clone(),
|
constellation_chan: self.layout_to_constellation_chan.clone(),
|
||||||
failure: failure,
|
panic_chan: panic_chan,
|
||||||
paint_chan: paint_chan,
|
paint_chan: paint_chan,
|
||||||
script_chan: self.control_chan.clone(),
|
script_chan: self.control_chan.clone(),
|
||||||
image_cache_thread: self.image_cache_thread.clone(),
|
image_cache_thread: self.image_cache_thread.clone(),
|
||||||
|
|
|
@ -41,7 +41,7 @@ use gfx_traits::Epoch;
|
||||||
use gfx_traits::LayerId;
|
use gfx_traits::LayerId;
|
||||||
use ipc_channel::ipc::{IpcReceiver, IpcSender};
|
use ipc_channel::ipc::{IpcReceiver, IpcSender};
|
||||||
use libc::c_void;
|
use libc::c_void;
|
||||||
use msg::constellation_msg::{ConstellationChan, Failure, PipelineId, WindowSizeData};
|
use msg::constellation_msg::{ConstellationChan, PanicMsg, PipelineId, WindowSizeData};
|
||||||
use msg::constellation_msg::{Key, KeyModifiers, KeyState, LoadData};
|
use msg::constellation_msg::{Key, KeyModifiers, KeyState, LoadData};
|
||||||
use msg::constellation_msg::{PipelineNamespaceId, SubpageId};
|
use msg::constellation_msg::{PipelineNamespaceId, SubpageId};
|
||||||
use msg::webdriver_msg::WebDriverScriptCommand;
|
use msg::webdriver_msg::WebDriverScriptCommand;
|
||||||
|
@ -93,10 +93,10 @@ pub struct NewLayoutInfo {
|
||||||
/// The paint channel, cast to `OptionalOpaqueIpcSender`. This is really an
|
/// The paint channel, cast to `OptionalOpaqueIpcSender`. This is really an
|
||||||
/// `Sender<LayoutToPaintMsg>`.
|
/// `Sender<LayoutToPaintMsg>`.
|
||||||
pub paint_chan: OptionalOpaqueIpcSender,
|
pub paint_chan: OptionalOpaqueIpcSender,
|
||||||
/// Information on what to do on thread failure.
|
|
||||||
pub failure: Failure,
|
|
||||||
/// A port on which layout can receive messages from the pipeline.
|
/// A port on which layout can receive messages from the pipeline.
|
||||||
pub pipeline_port: IpcReceiver<LayoutControlMsg>,
|
pub pipeline_port: IpcReceiver<LayoutControlMsg>,
|
||||||
|
/// A channel for sending panics on
|
||||||
|
pub panic_chan: ConstellationChan<PanicMsg>,
|
||||||
/// A shutdown channel so that layout can notify others when it's done.
|
/// A shutdown channel so that layout can notify others when it's done.
|
||||||
pub layout_shutdown_chan: IpcSender<()>,
|
pub layout_shutdown_chan: IpcSender<()>,
|
||||||
/// A shutdown channel so that layout can tell the content process to shut down when it's done.
|
/// A shutdown channel so that layout can tell the content process to shut down when it's done.
|
||||||
|
@ -315,10 +315,10 @@ pub struct InitialScriptState {
|
||||||
pub constellation_chan: ConstellationChan<ScriptMsg>,
|
pub constellation_chan: ConstellationChan<ScriptMsg>,
|
||||||
/// A channel for the layout thread to send messages to the constellation.
|
/// A channel for the layout thread to send messages to the constellation.
|
||||||
pub layout_to_constellation_chan: ConstellationChan<LayoutMsg>,
|
pub layout_to_constellation_chan: ConstellationChan<LayoutMsg>,
|
||||||
|
/// A channel for sending panics to the constellation.
|
||||||
|
pub panic_chan: ConstellationChan<PanicMsg>,
|
||||||
/// A channel to schedule timer events.
|
/// A channel to schedule timer events.
|
||||||
pub scheduler_chan: IpcSender<TimerEventRequest>,
|
pub scheduler_chan: IpcSender<TimerEventRequest>,
|
||||||
/// Information that script sends out when it panics.
|
|
||||||
pub failure_info: Failure,
|
|
||||||
/// A channel to the resource manager thread.
|
/// A channel to the resource manager thread.
|
||||||
pub resource_thread: ResourceThread,
|
pub resource_thread: ResourceThread,
|
||||||
/// A channel to the storage thread.
|
/// A channel to the storage thread.
|
||||||
|
|
|
@ -12,8 +12,8 @@ use canvas_traits::CanvasMsg;
|
||||||
use euclid::point::Point2D;
|
use euclid::point::Point2D;
|
||||||
use euclid::size::Size2D;
|
use euclid::size::Size2D;
|
||||||
use ipc_channel::ipc::IpcSender;
|
use ipc_channel::ipc::IpcSender;
|
||||||
use msg::constellation_msg::{Failure, NavigationDirection, PipelineId};
|
|
||||||
use msg::constellation_msg::{LoadData, SubpageId};
|
use msg::constellation_msg::{LoadData, SubpageId};
|
||||||
|
use msg::constellation_msg::{NavigationDirection, PipelineId};
|
||||||
use offscreen_gl_context::{GLContextAttributes, GLLimits};
|
use offscreen_gl_context::{GLContextAttributes, GLLimits};
|
||||||
use style_traits::cursor::Cursor;
|
use style_traits::cursor::Cursor;
|
||||||
use style_traits::viewport::ViewportConstraints;
|
use style_traits::viewport::ViewportConstraints;
|
||||||
|
@ -24,20 +24,12 @@ use url::Url;
|
||||||
pub enum LayoutMsg {
|
pub enum LayoutMsg {
|
||||||
/// Indicates whether this pipeline is currently running animations.
|
/// Indicates whether this pipeline is currently running animations.
|
||||||
ChangeRunningAnimationsState(PipelineId, AnimationState),
|
ChangeRunningAnimationsState(PipelineId, AnimationState),
|
||||||
/// Layout thread failure.
|
|
||||||
Failure(Failure),
|
|
||||||
/// Requests that the constellation inform the compositor of the a cursor change.
|
/// Requests that the constellation inform the compositor of the a cursor change.
|
||||||
SetCursor(Cursor),
|
SetCursor(Cursor),
|
||||||
/// Notifies the constellation that the viewport has been constrained in some manner
|
/// Notifies the constellation that the viewport has been constrained in some manner
|
||||||
ViewportConstrained(PipelineId, ViewportConstraints),
|
ViewportConstrained(PipelineId, ViewportConstraints),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<Failure> for LayoutMsg {
|
|
||||||
fn from(failure: Failure) -> LayoutMsg {
|
|
||||||
LayoutMsg::Failure(failure)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Messages from the script to the constellation.
|
/// Messages from the script to the constellation.
|
||||||
#[derive(Deserialize, Serialize)]
|
#[derive(Deserialize, Serialize)]
|
||||||
pub enum ScriptMsg {
|
pub enum ScriptMsg {
|
||||||
|
@ -55,8 +47,6 @@ pub enum ScriptMsg {
|
||||||
/// Causes a `load` event to be dispatched to any enclosing frame context element
|
/// Causes a `load` event to be dispatched to any enclosing frame context element
|
||||||
/// for the given pipeline.
|
/// for the given pipeline.
|
||||||
DOMLoad(PipelineId),
|
DOMLoad(PipelineId),
|
||||||
/// Script thread failure.
|
|
||||||
Failure(Failure),
|
|
||||||
/// Notifies the constellation that this frame has received focus.
|
/// Notifies the constellation that this frame has received focus.
|
||||||
Focus(PipelineId),
|
Focus(PipelineId),
|
||||||
/// Re-send a mouse button event that was sent to the parent window.
|
/// Re-send a mouse button event that was sent to the parent window.
|
||||||
|
@ -92,9 +82,3 @@ pub enum ScriptMsg {
|
||||||
/// Update the pipeline Url, which can change after redirections.
|
/// Update the pipeline Url, which can change after redirections.
|
||||||
SetFinalUrl(PipelineId, Url),
|
SetFinalUrl(PipelineId, Url),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<Failure> for ScriptMsg {
|
|
||||||
fn from(failure: Failure) -> ScriptMsg {
|
|
||||||
ScriptMsg::Failure(failure)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -17,11 +17,16 @@ static HOOK_SET: Once = ONCE_INIT;
|
||||||
/// TLS data pertaining to how failures should be reported
|
/// TLS data pertaining to how failures should be reported
|
||||||
pub struct PanicHandlerLocal {
|
pub struct PanicHandlerLocal {
|
||||||
/// failure handler passed through spawn_named_with_send_on_failure
|
/// failure handler passed through spawn_named_with_send_on_failure
|
||||||
pub fail: Box<(FnBox(&(Any + Send))) + Send + 'static>
|
pub fail: Box<FnBox(&Any)>
|
||||||
}
|
}
|
||||||
|
|
||||||
thread_local!(pub static LOCAL_INFO: RefCell<Option<PanicHandlerLocal>> = RefCell::new(None));
|
thread_local!(pub static LOCAL_INFO: RefCell<Option<PanicHandlerLocal>> = RefCell::new(None));
|
||||||
|
|
||||||
|
/// Set the thread-local panic hook
|
||||||
|
pub fn set_thread_local_hook(local: Box<FnBox(&Any)>) {
|
||||||
|
LOCAL_INFO.with(|i| *i.borrow_mut() = Some(PanicHandlerLocal { fail: local }));
|
||||||
|
}
|
||||||
|
|
||||||
/// Initiates the custom panic hook
|
/// Initiates the custom panic hook
|
||||||
/// Should be called in main() after arguments have been parsed
|
/// Should be called in main() after arguments have been parsed
|
||||||
pub fn initiate_panic_hook() {
|
pub fn initiate_panic_hook() {
|
||||||
|
|
|
@ -6,97 +6,33 @@ use ipc_channel::ipc::IpcSender;
|
||||||
use panicking;
|
use panicking;
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
use std::any::Any;
|
use std::any::Any;
|
||||||
use std::borrow::ToOwned;
|
|
||||||
use std::sync::mpsc::Sender;
|
|
||||||
use std::thread;
|
use std::thread;
|
||||||
use thread_state;
|
use thread_state;
|
||||||
|
|
||||||
pub type PanicReason = Option<String>;
|
|
||||||
|
|
||||||
pub fn spawn_named<F>(name: String, f: F)
|
pub fn spawn_named<F>(name: String, f: F)
|
||||||
where F: FnOnce() + Send + 'static
|
where F: FnOnce() + Send + 'static
|
||||||
{
|
{
|
||||||
spawn_named_with_send_on_failure_maybe(name, None, f, |_| {});
|
thread::Builder::new().name(name).spawn(f).expect("Thread spawn failed");
|
||||||
}
|
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Arrange to send a particular message to a channel if the thread fails.
|
/// 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,
|
pub fn spawn_named_with_send_on_panic<F, Id>(name: String,
|
||||||
state: thread_state::ThreadState,
|
state: thread_state::ThreadState,
|
||||||
f: F,
|
f: F,
|
||||||
mut msg: T,
|
id: Id,
|
||||||
mut dest: S)
|
panic_chan: IpcSender<(Id, String)>)
|
||||||
where F: FnOnce() + Send + 'static,
|
where F: FnOnce() + Send + 'static,
|
||||||
T: Send + AddFailureDetails + 'static,
|
Id: Copy + Send + Serialize + 'static,
|
||||||
S: Send + SendOnFailure + 'static,
|
|
||||||
S::Value: From<T>,
|
|
||||||
{
|
{
|
||||||
spawn_named_with_send_on_failure_maybe(name, Some(state), f,
|
thread::Builder::new().name(name).spawn(move || {
|
||||||
move |err| {
|
thread_state::initialize(state);
|
||||||
msg.add_panic_object(err);
|
panicking::set_thread_local_hook(Box::new(move |payload: &Any| {
|
||||||
dest.send_on_failure(S::Value::from(msg));
|
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>"));
|
||||||
fn spawn_named_with_send_on_failure_maybe<F, G>(name: String,
|
let _ = panic_chan.send((id, reason));
|
||||||
state: Option<thread_state::ThreadState>,
|
}));
|
||||||
f: F,
|
f()
|
||||||
fail: G)
|
}).expect("Thread spawn failed");
|
||||||
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();
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue