mirror of
https://github.com/servo/servo.git
synced 2025-09-18 19:08:22 +01:00
generic channel: Migrate background hang monitor to GenericChannel (#39345)
Refactor the background hang monitor channels to use GenericChannel. Deserialization errors of `BackgroundHangMonitorControlMsg` are now logged and ignored instead of causing a panic. Testing: No major functional changes. Covered by BHM tests. GenericChannel is also already widely used in servo. Part of #38912 --------- Signed-off-by: Jonathan Schwender <schwenderjonathan@gmail.com>
This commit is contained in:
parent
6cba44e0e3
commit
d848bd2759
4 changed files with 36 additions and 31 deletions
|
@ -11,9 +11,8 @@ use background_hang_monitor_api::{
|
|||
BackgroundHangMonitorExitSignal, BackgroundHangMonitorRegister, HangAlert, HangAnnotation,
|
||||
HangMonitorAlert, MonitoredComponentId,
|
||||
};
|
||||
use base::generic_channel::{GenericReceiver, GenericSender, RoutedReceiver};
|
||||
use crossbeam_channel::{Receiver, Sender, after, never, select, unbounded};
|
||||
use ipc_channel::ipc::{IpcReceiver, IpcSender};
|
||||
use ipc_channel::router::ROUTER;
|
||||
use rustc_hash::FxHashMap;
|
||||
|
||||
use crate::sampler::{NativeStack, Sampler};
|
||||
|
@ -28,8 +27,8 @@ impl HangMonitorRegister {
|
|||
/// Start a new hang monitor worker, and return a handle to register components for monitoring,
|
||||
/// as well as a join handle on the worker thread.
|
||||
pub fn init(
|
||||
constellation_chan: IpcSender<HangMonitorAlert>,
|
||||
control_port: IpcReceiver<BackgroundHangMonitorControlMsg>,
|
||||
constellation_chan: GenericSender<HangMonitorAlert>,
|
||||
control_port: GenericReceiver<BackgroundHangMonitorControlMsg>,
|
||||
monitoring_enabled: bool,
|
||||
) -> (Box<dyn BackgroundHangMonitorRegister>, JoinHandle<()>) {
|
||||
let (sender, port) = unbounded();
|
||||
|
@ -211,9 +210,9 @@ struct Sample(MonitoredComponentId, Instant, NativeStack);
|
|||
struct BackgroundHangMonitorWorker {
|
||||
component_names: FxHashMap<MonitoredComponentId, String>,
|
||||
monitored_components: FxHashMap<MonitoredComponentId, MonitoredComponent>,
|
||||
constellation_chan: IpcSender<HangMonitorAlert>,
|
||||
constellation_chan: GenericSender<HangMonitorAlert>,
|
||||
port: Receiver<(MonitoredComponentId, MonitoredComponentMsg)>,
|
||||
control_port: Receiver<BackgroundHangMonitorControlMsg>,
|
||||
control_port: RoutedReceiver<BackgroundHangMonitorControlMsg>,
|
||||
sampling_duration: Option<Duration>,
|
||||
sampling_max_duration: Option<Duration>,
|
||||
last_sample: Instant,
|
||||
|
@ -229,12 +228,12 @@ type MonitoredComponentReceiver = Receiver<(MonitoredComponentId, MonitoredCompo
|
|||
|
||||
impl BackgroundHangMonitorWorker {
|
||||
fn new(
|
||||
constellation_chan: IpcSender<HangMonitorAlert>,
|
||||
control_port: IpcReceiver<BackgroundHangMonitorControlMsg>,
|
||||
constellation_chan: GenericSender<HangMonitorAlert>,
|
||||
control_port: GenericReceiver<BackgroundHangMonitorControlMsg>,
|
||||
port: MonitoredComponentReceiver,
|
||||
monitoring_enabled: bool,
|
||||
) -> Self {
|
||||
let control_port = ROUTER.route_ipc_receiver_to_new_crossbeam_receiver(control_port);
|
||||
let control_port = control_port.route_preserving_errors();
|
||||
Self {
|
||||
component_names: Default::default(),
|
||||
monitored_components: Default::default(),
|
||||
|
@ -318,7 +317,7 @@ impl BackgroundHangMonitorWorker {
|
|||
},
|
||||
recv(self.control_port) -> event => {
|
||||
match event {
|
||||
Ok(BackgroundHangMonitorControlMsg::ToggleSampler(rate, max_duration)) => {
|
||||
Ok(Ok(BackgroundHangMonitorControlMsg::ToggleSampler(rate, max_duration))) => {
|
||||
if self.sampling_duration.is_some() {
|
||||
println!("Enabling profiler.");
|
||||
self.finish_sampled_profile();
|
||||
|
@ -331,7 +330,7 @@ impl BackgroundHangMonitorWorker {
|
|||
}
|
||||
None
|
||||
},
|
||||
Ok(BackgroundHangMonitorControlMsg::Exit) => {
|
||||
Ok(Ok(BackgroundHangMonitorControlMsg::Exit)) => {
|
||||
for component in self.monitored_components.values_mut() {
|
||||
component.exit_signal.signal_to_exit();
|
||||
}
|
||||
|
@ -347,6 +346,10 @@ impl BackgroundHangMonitorWorker {
|
|||
// which we know has happened when `self.port` disconnects.
|
||||
None
|
||||
},
|
||||
Ok(Err(e)) => {
|
||||
log::warn!("BackgroundHangMonitorWorker control message deserialization error: {e:?}");
|
||||
None
|
||||
},
|
||||
Err(_) => return false,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,6 +14,7 @@ use background_hang_monitor_api::{
|
|||
BackgroundHangMonitorControlMsg, BackgroundHangMonitorExitSignal, HangAlert, HangAnnotation,
|
||||
HangMonitorAlert, MonitoredComponentId, MonitoredComponentType, ScriptHangAnnotation,
|
||||
};
|
||||
use base::generic_channel;
|
||||
use base::id::TEST_PIPELINE_ID;
|
||||
use ipc_channel::ipc;
|
||||
|
||||
|
@ -24,8 +25,9 @@ fn test_hang_monitoring() {
|
|||
let _lock = SERIAL.lock().unwrap();
|
||||
|
||||
let (background_hang_monitor_ipc_sender, background_hang_monitor_receiver) =
|
||||
ipc::channel().expect("ipc channel failure");
|
||||
let (_sampler_sender, sampler_receiver) = ipc::channel().expect("ipc channel failure");
|
||||
generic_channel::channel().expect("ipc channel failure");
|
||||
let (_sampler_sender, sampler_receiver) =
|
||||
generic_channel::channel().expect("ipc channel failure");
|
||||
|
||||
let (background_hang_monitor_register, join_handle) = HangMonitorRegister::init(
|
||||
background_hang_monitor_ipc_sender.clone(),
|
||||
|
@ -140,8 +142,9 @@ fn test_hang_monitoring_unregister() {
|
|||
let _lock = SERIAL.lock().unwrap();
|
||||
|
||||
let (background_hang_monitor_ipc_sender, background_hang_monitor_receiver) =
|
||||
ipc::channel().expect("ipc channel failure");
|
||||
let (_sampler_sender, sampler_receiver) = ipc::channel().expect("ipc channel failure");
|
||||
generic_channel::channel().expect("ipc channel failure");
|
||||
let (_sampler_sender, sampler_receiver) =
|
||||
generic_channel::channel().expect("ipc channel failure");
|
||||
|
||||
let (background_hang_monitor_register, join_handle) = HangMonitorRegister::init(
|
||||
background_hang_monitor_ipc_sender.clone(),
|
||||
|
@ -225,8 +228,9 @@ fn test_hang_monitoring_exit_signal_inner(op_order: fn(&mut dyn FnMut(), &mut dy
|
|||
let _lock = SERIAL.lock().unwrap();
|
||||
|
||||
let (background_hang_monitor_ipc_sender, _background_hang_monitor_receiver) =
|
||||
ipc::channel().expect("ipc channel failure");
|
||||
let (control_sender, control_receiver) = ipc::channel().expect("ipc channel failure");
|
||||
generic_channel::channel().expect("ipc channel failure");
|
||||
let (control_sender, control_receiver) =
|
||||
generic_channel::channel().expect("ipc channel failure");
|
||||
|
||||
struct BHMExitSignal {
|
||||
closing: Arc<AtomicBool>,
|
||||
|
|
|
@ -309,15 +309,15 @@ pub struct Constellation<STF, SWF> {
|
|||
/// Channels to control all background-hang monitors.
|
||||
/// TODO: store them on the relevant BrowsingContextGroup,
|
||||
/// so that they could be controlled on a "per-tab/event-loop" basis.
|
||||
background_monitor_control_senders: Vec<IpcSender<BackgroundHangMonitorControlMsg>>,
|
||||
background_monitor_control_senders: Vec<GenericSender<BackgroundHangMonitorControlMsg>>,
|
||||
|
||||
/// A channel for the background hang monitor to send messages
|
||||
/// to the constellation.
|
||||
background_hang_monitor_sender: IpcSender<HangMonitorAlert>,
|
||||
background_hang_monitor_sender: GenericSender<HangMonitorAlert>,
|
||||
|
||||
/// A channel for the constellation to receiver messages
|
||||
/// from the background hang monitor.
|
||||
background_hang_monitor_receiver: Receiver<Result<HangMonitorAlert, IpcError>>,
|
||||
background_hang_monitor_receiver: RoutedReceiver<HangMonitorAlert>,
|
||||
|
||||
/// A factory for creating layouts. This allows customizing the kind
|
||||
/// of layout created for a [`Constellation`] and prevents a circular crate
|
||||
|
@ -627,11 +627,9 @@ where
|
|||
let namespace_receiver = namespace_ipc_receiver.route_preserving_errors();
|
||||
|
||||
let (background_hang_monitor_ipc_sender, background_hang_monitor_ipc_receiver) =
|
||||
ipc::channel().expect("ipc channel failure");
|
||||
generic_channel::channel().expect("ipc channel failure");
|
||||
let background_hang_monitor_receiver =
|
||||
route_ipc_receiver_to_new_crossbeam_receiver_preserving_errors(
|
||||
background_hang_monitor_ipc_receiver,
|
||||
);
|
||||
background_hang_monitor_ipc_receiver.route_preserving_errors();
|
||||
|
||||
// If we are in multiprocess mode,
|
||||
// a dedicated per-process hang monitor will be initialized later inside the content process.
|
||||
|
@ -646,7 +644,7 @@ where
|
|||
let (
|
||||
background_hang_monitor_control_ipc_sender,
|
||||
background_hang_monitor_control_ipc_receiver,
|
||||
) = ipc::channel().expect("ipc channel failure");
|
||||
) = generic_channel::channel().expect("ipc channel failure");
|
||||
let (register, join_handle) = HangMonitorRegister::init(
|
||||
background_hang_monitor_ipc_sender.clone(),
|
||||
background_hang_monitor_control_ipc_receiver,
|
||||
|
|
|
@ -12,7 +12,7 @@ use background_hang_monitor_api::{
|
|||
BackgroundHangMonitorControlMsg, BackgroundHangMonitorRegister, HangMonitorAlert,
|
||||
};
|
||||
use base::Epoch;
|
||||
use base::generic_channel::{GenericReceiver, GenericSender};
|
||||
use base::generic_channel::{self, GenericReceiver, GenericSender};
|
||||
use base::id::{
|
||||
BrowsingContextId, HistoryStateId, PipelineId, PipelineNamespace, PipelineNamespaceId,
|
||||
PipelineNamespaceRequest, WebViewId,
|
||||
|
@ -144,7 +144,7 @@ pub struct InitialPipelineState {
|
|||
pub background_monitor_register: Option<Box<dyn BackgroundHangMonitorRegister>>,
|
||||
|
||||
/// A channel for the background hang monitor to send messages to the constellation.
|
||||
pub background_hang_monitor_to_constellation_chan: IpcSender<HangMonitorAlert>,
|
||||
pub background_hang_monitor_to_constellation_chan: GenericSender<HangMonitorAlert>,
|
||||
|
||||
/// A fatory for creating layouts to be used by the ScriptThread.
|
||||
pub layout_factory: Arc<dyn LayoutFactory>,
|
||||
|
@ -219,7 +219,7 @@ pub struct InitialPipelineState {
|
|||
|
||||
pub struct NewPipeline {
|
||||
pub pipeline: Pipeline,
|
||||
pub bhm_control_chan: Option<IpcSender<BackgroundHangMonitorControlMsg>>,
|
||||
pub bhm_control_chan: Option<GenericSender<BackgroundHangMonitorControlMsg>>,
|
||||
pub lifeline: Option<(IpcReceiver<()>, Process)>,
|
||||
pub join_handle: Option<JoinHandle<()>>,
|
||||
}
|
||||
|
@ -325,7 +325,7 @@ impl Pipeline {
|
|||
// Yes, that's all there is to it!
|
||||
let multiprocess_data = if opts::get().multiprocess {
|
||||
let (bhm_control_chan, bhm_control_port) =
|
||||
ipc::channel().expect("Sampler chan");
|
||||
generic_channel::channel().expect("Sampler chan");
|
||||
unprivileged_pipeline_content.bhm_control_port = Some(bhm_control_port);
|
||||
let (sender, receiver) =
|
||||
ipc::channel().expect("Failed to create lifeline channel");
|
||||
|
@ -487,8 +487,8 @@ pub struct UnprivilegedPipelineContent {
|
|||
namespace_request_sender: GenericSender<PipelineNamespaceRequest>,
|
||||
script_to_constellation_chan: ScriptToConstellationChan,
|
||||
script_to_embedder_chan: ScriptToEmbedderChan,
|
||||
background_hang_monitor_to_constellation_chan: IpcSender<HangMonitorAlert>,
|
||||
bhm_control_port: Option<IpcReceiver<BackgroundHangMonitorControlMsg>>,
|
||||
background_hang_monitor_to_constellation_chan: GenericSender<HangMonitorAlert>,
|
||||
bhm_control_port: Option<GenericReceiver<BackgroundHangMonitorControlMsg>>,
|
||||
devtools_ipc_sender: Option<IpcSender<ScriptToDevtoolsControlMsg>>,
|
||||
#[cfg(feature = "bluetooth")]
|
||||
bluetooth_thread: IpcSender<BluetoothRequest>,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue