Removed sources of panic from piepline.rs.

This commit is contained in:
Alan Jeffrey 2016-04-05 15:08:30 -05:00
parent 04600458e6
commit 01b6e4a2c1

View file

@ -124,13 +124,19 @@ impl Pipeline {
/// Returns the channels wrapped in a struct. /// Returns the channels wrapped in a struct.
pub fn create<LTF, STF>(state: InitialPipelineState) pub fn create<LTF, STF>(state: InitialPipelineState)
-> (Pipeline, UnprivilegedPipelineContent, PrivilegedPipelineContent) -> (Pipeline, UnprivilegedPipelineContent, PrivilegedPipelineContent)
where LTF: LayoutThreadFactory, STF: ScriptThreadFactory { where LTF: LayoutThreadFactory, STF: ScriptThreadFactory {
// Note: we allow channel creation to panic, since recovering from this
// probably requires a general low-memory strategy.
let (layout_to_paint_chan, layout_to_paint_port) = util::ipc::optional_ipc_channel(); let (layout_to_paint_chan, layout_to_paint_port) = util::ipc::optional_ipc_channel();
let (chrome_to_paint_chan, chrome_to_paint_port) = channel(); let (chrome_to_paint_chan, chrome_to_paint_port) = channel();
let (paint_shutdown_chan, paint_shutdown_port) = ipc::channel().unwrap(); let (paint_shutdown_chan, paint_shutdown_port) = ipc::channel()
let (layout_shutdown_chan, layout_shutdown_port) = ipc::channel().unwrap(); .expect("Pipeline paint shutdown chan");
let (pipeline_chan, pipeline_port) = ipc::channel().unwrap(); let (layout_shutdown_chan, layout_shutdown_port) = ipc::channel()
let (script_to_compositor_chan, script_to_compositor_port) = ipc::channel().unwrap(); .expect("Pipeline layout shutdown chan");
let (pipeline_chan, pipeline_port) = ipc::channel()
.expect("Pipeline main chan");;
let (script_to_compositor_chan, script_to_compositor_port) = ipc::channel()
.expect("Pipeline script to compositor chan");
let mut pipeline_port = Some(pipeline_port); let mut pipeline_port = Some(pipeline_port);
let failure = Failure { let failure = Failure {
@ -148,17 +154,22 @@ impl Pipeline {
// Route messages coming from content to devtools as appropriate. // Route messages coming from content to devtools as appropriate.
let script_to_devtools_chan = state.devtools_chan.as_ref().map(|devtools_chan| { let script_to_devtools_chan = state.devtools_chan.as_ref().map(|devtools_chan| {
let (script_to_devtools_chan, script_to_devtools_port) = ipc::channel().unwrap(); let (script_to_devtools_chan, script_to_devtools_port) = ipc::channel()
.expect("Pipeline script to devtools chan");
let devtools_chan = (*devtools_chan).clone(); let devtools_chan = (*devtools_chan).clone();
ROUTER.add_route(script_to_devtools_port.to_opaque(), box move |message| { ROUTER.add_route(script_to_devtools_port.to_opaque(), box move |message| {
let message: ScriptToDevtoolsControlMsg = message.to().unwrap(); match message.to::<ScriptToDevtoolsControlMsg>() {
devtools_chan.send(DevtoolsControlMsg::FromScript(message)).unwrap() Err(e) => error!("Cast to ScriptToDevtoolsControlMsg failed ({}).", e),
Ok(message) => if let Err(e) = devtools_chan.send(DevtoolsControlMsg::FromScript(message)) {
warn!("Sending to devtools failed ({})", e)
},
}
}); });
script_to_devtools_chan script_to_devtools_chan
}); });
let (layout_content_process_shutdown_chan, layout_content_process_shutdown_port) = let (layout_content_process_shutdown_chan, layout_content_process_shutdown_port) =
ipc::channel().unwrap(); ipc::channel().expect("Pipeline layout content shutdown chan");
let (script_chan, script_port) = match state.script_chan { let (script_chan, script_port) = match state.script_chan {
Some(script_chan) => { Some(script_chan) => {
@ -171,23 +182,25 @@ impl Pipeline {
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, failure: failure,
pipeline_port: mem::replace(&mut pipeline_port, None).unwrap(), pipeline_port: mem::replace(&mut 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(),
content_process_shutdown_chan: layout_content_process_shutdown_chan.clone(), content_process_shutdown_chan: layout_content_process_shutdown_chan.clone(),
}; };
script_chan.send(ConstellationControlMsg::AttachLayout(new_layout_info)) if let Err(e) = script_chan.send(ConstellationControlMsg::AttachLayout(new_layout_info)) {
.unwrap(); warn!("Sending to script during pipeline creation failed ({})", e);
}
(script_chan, None) (script_chan, None)
} }
None => { None => {
let (script_chan, script_port) = ipc::channel().unwrap(); let (script_chan, script_port) = ipc::channel().expect("Pipeline script chan");
(script_chan, Some(script_port)) (script_chan, Some(script_port))
} }
}; };
let (script_content_process_shutdown_chan, script_content_process_shutdown_port) = let (script_content_process_shutdown_chan, script_content_process_shutdown_port) =
ipc::channel().unwrap(); ipc::channel().expect("Pipeline script content process shutdown chan");
let pipeline = Pipeline::new(state.id, let pipeline = Pipeline::new(state.id,
state.parent_info, state.parent_info,
@ -295,9 +308,12 @@ impl Pipeline {
// The compositor wants to know when pipelines shut down too. // The compositor wants to know when pipelines shut down too.
// It may still have messages to process from these other threads // It may still have messages to process from these other threads
// before they can be safely shut down. // before they can be safely shut down.
let (sender, receiver) = ipc::channel().unwrap(); if let Ok((sender, receiver)) = ipc::channel() {
self.compositor_proxy.send(CompositorMsg::PipelineExited(self.id, sender)); self.compositor_proxy.send(CompositorMsg::PipelineExited(self.id, sender));
receiver.recv().unwrap(); if let Err(e) = receiver.recv() {
warn!("Sending exit message failed ({}).", e);
}
}
// Script thread handles shutting down layout, and layout handles shutting down the painter. // Script thread handles shutting down layout, and layout handles shutting down the painter.
// For now, if the script thread has failed, we give up on clean shutdown. // For now, if the script thread has failed, we give up on clean shutdown.
@ -312,18 +328,28 @@ impl Pipeline {
} }
pub fn freeze(&self) { pub fn freeze(&self) {
let _ = self.script_chan.send(ConstellationControlMsg::Freeze(self.id)).unwrap(); if let Err(e) = self.script_chan.send(ConstellationControlMsg::Freeze(self.id)) {
warn!("Sending freeze message failed ({}).", e);
}
} }
pub fn thaw(&self) { pub fn thaw(&self) {
let _ = self.script_chan.send(ConstellationControlMsg::Thaw(self.id)).unwrap(); if let Err(e) = self.script_chan.send(ConstellationControlMsg::Thaw(self.id)) {
warn!("Sending freeze message failed ({}).", e);
}
} }
pub fn force_exit(&self) { pub fn force_exit(&self) {
let _ = self.script_chan.send(ConstellationControlMsg::ExitPipeline(self.id)).unwrap(); if let Err(e) = self.script_chan.send(ConstellationControlMsg::ExitPipeline(self.id)) {
let _ = self.chrome_to_paint_chan.send(ChromeToPaintMsg::Exit); warn!("Sending script exit message failed ({}).", e);
}
if let Err(e) = self.chrome_to_paint_chan.send(ChromeToPaintMsg::Exit) {
warn!("Sending paint exit message failed ({}).", e);
}
let LayoutControlChan(ref layout_channel) = self.layout_chan; let LayoutControlChan(ref layout_channel) = self.layout_chan;
let _ = layout_channel.send(LayoutControlMsg::ExitNow).unwrap(); if let Err(e) = layout_channel.send(LayoutControlMsg::ExitNow) {
warn!("Sending layout exit message failed ({}).", e);
}
} }
pub fn to_sendable(&self) -> CompositionPipeline { pub fn to_sendable(&self) -> CompositionPipeline {
@ -340,8 +366,10 @@ impl Pipeline {
} }
pub fn remove_child(&mut self, frame_id: FrameId) { pub fn remove_child(&mut self, frame_id: FrameId) {
let index = self.children.iter().position(|id| *id == frame_id).unwrap(); match self.children.iter().position(|id| *id == frame_id) {
self.children.remove(index); None => return warn!("Pipeline remove child already removed ({:?}).", frame_id),
Some(index) => self.children.remove(index),
};
} }
pub fn trigger_mozbrowser_event(&self, pub fn trigger_mozbrowser_event(&self,
@ -352,7 +380,9 @@ impl Pipeline {
let event = ConstellationControlMsg::MozBrowserEvent(self.id, let event = ConstellationControlMsg::MozBrowserEvent(self.id,
subpage_id, subpage_id,
event); event);
self.script_chan.send(event).unwrap(); if let Err(e) = self.script_chan.send(event) {
warn!("Sending mozbrowser event to script failed ({}).", e);
}
} }
} }
@ -399,7 +429,7 @@ impl UnprivilegedPipelineContent {
parent_info: self.parent_info, parent_info: self.parent_info,
compositor: self.script_to_compositor_chan, compositor: self.script_to_compositor_chan,
control_chan: self.script_chan.clone(), control_chan: self.script_chan.clone(),
control_port: mem::replace(&mut self.script_port, None).unwrap(), control_port: mem::replace(&mut self.script_port, None).expect("No script port."),
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(),
@ -420,7 +450,7 @@ impl UnprivilegedPipelineContent {
self.load_data.url.clone(), self.load_data.url.clone(),
self.parent_info.is_some(), self.parent_info.is_some(),
layout_pair, layout_pair,
self.pipeline_port.unwrap(), self.pipeline_port.expect("No pipeline port."),
self.layout_to_constellation_chan, self.layout_to_constellation_chan,
self.failure, self.failure,
self.script_chan.clone(), self.script_chan.clone(),
@ -434,8 +464,8 @@ impl UnprivilegedPipelineContent {
self.webrender_api_sender); self.webrender_api_sender);
if wait_for_completion { if wait_for_completion {
self.script_content_process_shutdown_port.recv().unwrap(); let _ = self.script_content_process_shutdown_port.recv();
self.layout_content_process_shutdown_port.recv().unwrap(); let _ = self.layout_content_process_shutdown_port.recv();
} }
} }