mirror of
https://github.com/servo/servo.git
synced 2025-06-25 17:44:33 +01:00
Adds indexeddb support to servo. At the moment heed is being used as the backend, although this can be swapped out by implementing `KvsEngine`. This PR adds a thread + a thread pool for Indexeddb related operations. Also `database_access_task_source` is added for Indexeddb related operations. This is a partial rewrite of #25214. (Reopened due to branching issue) Fixes #6963 --------- Signed-off-by: Ashwin Naren <arihant2math@gmail.com> Signed-off-by: Josh Matthews <josh@joshmatthews.net> Co-authored-by: Rasmus Viitanen <rasviitanen@gmail.com> Co-authored-by: Josh Matthews <josh@joshmatthews.net>
213 lines
6.4 KiB
Rust
213 lines
6.4 KiB
Rust
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
|
|
|
#![deny(unsafe_code)]
|
|
|
|
//! An API interface to the BackgroundHangMonitor.
|
|
|
|
use std::time::Duration;
|
|
use std::{fmt, mem};
|
|
|
|
use base::id::PipelineId;
|
|
use ipc_channel::ipc::IpcSender;
|
|
use serde::{Deserialize, Serialize};
|
|
|
|
#[derive(Clone, Copy, Debug, Deserialize, Serialize)]
|
|
/// The equivalent of script::script_runtime::ScriptEventCategory
|
|
pub enum ScriptHangAnnotation {
|
|
AttachLayout,
|
|
ConstellationMsg,
|
|
DatabaseAccessEvent,
|
|
DevtoolsMsg,
|
|
DocumentEvent,
|
|
FileRead,
|
|
FontLoading,
|
|
FormPlannedNavigation,
|
|
ImageCacheMsg,
|
|
InputEvent,
|
|
HistoryEvent,
|
|
NetworkEvent,
|
|
Rendering,
|
|
Resize,
|
|
ScriptEvent,
|
|
SetScrollState,
|
|
SetViewport,
|
|
StylesheetLoad,
|
|
TimerEvent,
|
|
UpdateReplacedElement,
|
|
WebSocketEvent,
|
|
WorkerEvent,
|
|
WorkletEvent,
|
|
ServiceWorkerEvent,
|
|
EnterFullscreen,
|
|
ExitFullscreen,
|
|
WebVREvent,
|
|
PerformanceTimelineTask,
|
|
PortMessage,
|
|
WebGPUMsg,
|
|
}
|
|
|
|
#[derive(Clone, Copy, Debug, Deserialize, Serialize)]
|
|
pub enum HangAnnotation {
|
|
Script(ScriptHangAnnotation),
|
|
}
|
|
|
|
/// Hang-alerts are sent by the monitor to the constellation.
|
|
#[derive(Deserialize, Serialize)]
|
|
pub enum HangMonitorAlert {
|
|
/// A component hang has been detected.
|
|
Hang(HangAlert),
|
|
/// Report a completed sampled profile.
|
|
Profile(Vec<u8>),
|
|
}
|
|
|
|
impl fmt::Debug for HangMonitorAlert {
|
|
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
|
|
match *self {
|
|
HangMonitorAlert::Hang(..) => write!(fmt, "Hang"),
|
|
HangMonitorAlert::Profile(..) => write!(fmt, "Profile"),
|
|
}
|
|
}
|
|
}
|
|
|
|
/// Hang-alerts are sent by the monitor to the constellation.
|
|
#[derive(Deserialize, Serialize)]
|
|
pub enum HangAlert {
|
|
/// Report a transient hang.
|
|
Transient(MonitoredComponentId, HangAnnotation),
|
|
/// Report a permanent hang.
|
|
Permanent(MonitoredComponentId, HangAnnotation, Option<HangProfile>),
|
|
}
|
|
|
|
impl fmt::Debug for HangAlert {
|
|
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
|
|
let (annotation, profile) = match self {
|
|
HangAlert::Transient(component_id, annotation) => {
|
|
write!(
|
|
fmt,
|
|
"\n The following component is experiencing a transient hang: \n {:?}",
|
|
component_id
|
|
)?;
|
|
(*annotation, None)
|
|
},
|
|
HangAlert::Permanent(component_id, annotation, profile) => {
|
|
write!(
|
|
fmt,
|
|
"\n The following component is experiencing a permanent hang: \n {:?}",
|
|
component_id
|
|
)?;
|
|
(*annotation, profile.clone())
|
|
},
|
|
};
|
|
|
|
write!(fmt, "\n Annotation for the hang:\n{:?}", annotation)?;
|
|
if let Some(profile) = profile {
|
|
write!(fmt, "\n {:?}", profile)?;
|
|
}
|
|
|
|
Ok(())
|
|
}
|
|
}
|
|
|
|
#[derive(Clone, Deserialize, Serialize)]
|
|
pub struct HangProfileSymbol {
|
|
pub name: Option<String>,
|
|
pub filename: Option<String>,
|
|
pub lineno: Option<u32>,
|
|
}
|
|
|
|
#[derive(Clone, Deserialize, Serialize)]
|
|
/// Info related to the activity of an hanging component.
|
|
pub struct HangProfile {
|
|
pub backtrace: Vec<HangProfileSymbol>,
|
|
}
|
|
|
|
impl fmt::Debug for HangProfile {
|
|
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
|
|
let hex_width = mem::size_of::<usize>() * 2 + 2;
|
|
|
|
write!(fmt, "HangProfile backtrace:")?;
|
|
|
|
if self.backtrace.is_empty() {
|
|
write!(fmt, "backtrace failed to resolve")?;
|
|
return Ok(());
|
|
}
|
|
|
|
for symbol in self.backtrace.iter() {
|
|
write!(fmt, "\n {:1$}", "", hex_width)?;
|
|
|
|
if let Some(ref name) = symbol.name {
|
|
write!(fmt, " - {}", name)?;
|
|
} else {
|
|
write!(fmt, " - <unknown>")?;
|
|
}
|
|
|
|
if let (Some(ref file), Some(ref line)) = (symbol.filename.as_ref(), symbol.lineno) {
|
|
write!(fmt, "\n {:3$}at {}:{}", "", file, line, hex_width)?;
|
|
}
|
|
}
|
|
|
|
Ok(())
|
|
}
|
|
}
|
|
|
|
#[derive(Clone, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
|
|
pub enum MonitoredComponentType {
|
|
Script,
|
|
}
|
|
|
|
#[derive(Clone, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
|
|
pub struct MonitoredComponentId(pub PipelineId, pub MonitoredComponentType);
|
|
|
|
/// A handle to register components for hang monitoring,
|
|
/// and to receive a means to communicate with the underlying hang monitor worker.
|
|
pub trait BackgroundHangMonitorRegister: BackgroundHangMonitorClone + Send {
|
|
/// Register a component for hang monitoring:
|
|
/// to be called from within the thread to be monitored for hangs.
|
|
fn register_component(
|
|
&self,
|
|
component: MonitoredComponentId,
|
|
transient_hang_timeout: Duration,
|
|
permanent_hang_timeout: Duration,
|
|
exit_signal: Option<Box<dyn BackgroundHangMonitorExitSignal>>,
|
|
) -> Box<dyn BackgroundHangMonitor>;
|
|
}
|
|
|
|
impl Clone for Box<dyn BackgroundHangMonitorRegister> {
|
|
fn clone(&self) -> Box<dyn BackgroundHangMonitorRegister> {
|
|
self.clone_box()
|
|
}
|
|
}
|
|
|
|
pub trait BackgroundHangMonitorClone {
|
|
fn clone_box(&self) -> Box<dyn BackgroundHangMonitorRegister>;
|
|
}
|
|
|
|
/// Proxy methods to communicate with the background hang monitor
|
|
pub trait BackgroundHangMonitor {
|
|
/// Notify the start of handling an event.
|
|
fn notify_activity(&self, annotation: HangAnnotation);
|
|
/// Notify the start of waiting for a new event to come in.
|
|
fn notify_wait(&self);
|
|
/// Unregister the component from monitor.
|
|
fn unregister(&self);
|
|
}
|
|
|
|
/// A means for the BHM to signal a monitored component to exit.
|
|
/// Useful when the component is hanging, and cannot be notified via the usual way.
|
|
/// The component should implement this in a way allowing for the signal to be received when hanging,
|
|
/// if at all.
|
|
pub trait BackgroundHangMonitorExitSignal: Send {
|
|
/// Called by the BHM, to notify the monitored component to exit.
|
|
fn signal_to_exit(&self);
|
|
}
|
|
|
|
/// Messages to control the sampling profiler.
|
|
#[derive(Deserialize, Serialize)]
|
|
pub enum BackgroundHangMonitorControlMsg {
|
|
/// Toggle the sampler, with a given sampling rate and max total sampling duration.
|
|
ToggleSampler(Duration, Duration),
|
|
/// Exit, and propagate the signal to monitored components.
|
|
Exit(IpcSender<()>),
|
|
}
|