Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Dedicated panic channel #10641

Merged
merged 1 commit into from Apr 19, 2016
Merged
Changes from all commits
Commits
File filter...
Filter file types
Jump to…
Jump to file
Failed to load files.

Always

Just for now

Added a dedicated panic channel.

  • Loading branch information
asajeffrey committed Apr 19, 2016
commit cfb066ef2024f05a13da842cedf833a8aa2e8cbe
@@ -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);
@@ -15,12 +15,11 @@ use euclid::rect::Rect;
use euclid::size::Size2D;
use font_cache_thread::FontCacheThread;
use font_context::FontContext;
use gfx_traits::PaintMsg as ConstellationMsg;
use gfx_traits::{Epoch, FrameTreeId, LayerId, LayerKind, LayerProperties, PaintListener};
use ipc_channel::ipc::IpcSender;
use layers::layers::{BufferRequest, LayerBuffer, LayerBufferSet};
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 profile_traits::mem::{self, ReportsChan};
use profile_traits::time;
@@ -394,14 +393,13 @@ impl<C> PaintThread<C> where C: PaintListener + Send + 'static {
layout_to_paint_port: Receiver<LayoutToPaintMsg>,
chrome_to_paint_port: Receiver<ChromeToPaintMsg>,
compositor: C,
constellation_chan: ConstellationChan<ConstellationMsg>,
panic_chan: ConstellationChan<PanicMsg>,
font_cache_thread: FontCacheThread,
failure_msg: Failure,
time_profiler_chan: time::ProfilerChan,
mem_profiler_chan: mem::ProfilerChan,
shutdown_chan: IpcSender<()>) {
let ConstellationChan(c) = constellation_chan.clone();
thread::spawn_named_with_send_on_failure(format!("PaintThread {:?}", id),
let ConstellationChan(c) = panic_chan.clone();
thread::spawn_named_with_send_on_panic(format!("PaintThread {:?}", id),
thread_state::PAINT,
move || {
{
@@ -441,7 +439,7 @@ impl<C> PaintThread<C> where C: PaintListener + Send + 'static {

debug!("paint_thread: shutdown_chan send");
shutdown_chan.send(()).unwrap();
}, failure_msg, c);
}, Some(id), c);
}

#[allow(unsafe_code)]
ProTip! Use n and p to navigate between commits in a pull request.
You can’t perform that action at this time.