fix(servo): lease persistent profile data
This commit is contained in:
@@ -1,7 +1,8 @@
|
|||||||
use std::{
|
use std::{
|
||||||
collections::HashMap,
|
collections::HashMap,
|
||||||
fs,
|
fs::{self, File, OpenOptions, TryLockError},
|
||||||
io::{self, BufRead},
|
io::{self, BufRead},
|
||||||
|
path::Path,
|
||||||
};
|
};
|
||||||
|
|
||||||
use ely_domain::{ProfileId, TabId, UrlText};
|
use ely_domain::{ProfileId, TabId, UrlText};
|
||||||
@@ -24,9 +25,12 @@ use super::{
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const PROFILE_DATA_LEASE_FILE: &str = ".ely-servo-sidecar.lock";
|
||||||
|
|
||||||
pub(super) fn run(args: LiveArgs) -> Result<(), LiveSidecarError> {
|
pub(super) fn run(args: LiveArgs) -> Result<(), LiveSidecarError> {
|
||||||
let LiveArgs { profile_data_dir, rendering_context, iosurface_mach_service } = args;
|
let LiveArgs { profile_data_dir, rendering_context, iosurface_mach_service } = args;
|
||||||
fs::create_dir_all(&profile_data_dir)?;
|
fs::create_dir_all(&profile_data_dir)?;
|
||||||
|
let _profile_data_lease = acquire_profile_data_lease(&profile_data_dir)?;
|
||||||
let rendering_context_kind = match rendering_context {
|
let rendering_context_kind = match rendering_context {
|
||||||
SidecarRenderingContext::Software => RenderingContextKind::Software,
|
SidecarRenderingContext::Software => RenderingContextKind::Software,
|
||||||
SidecarRenderingContext::Hardware => RenderingContextKind::Hardware,
|
SidecarRenderingContext::Hardware => RenderingContextKind::Hardware,
|
||||||
@@ -84,6 +88,22 @@ pub(super) fn run(args: LiveArgs) -> Result<(), LiveSidecarError> {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn acquire_profile_data_lease(profile_data_dir: &Path) -> Result<File, LiveSidecarError> {
|
||||||
|
let lease = OpenOptions::new()
|
||||||
|
.create(true)
|
||||||
|
.read(true)
|
||||||
|
.write(true)
|
||||||
|
.truncate(false)
|
||||||
|
.open(profile_data_dir.join(PROFILE_DATA_LEASE_FILE))?;
|
||||||
|
match lease.try_lock() {
|
||||||
|
Ok(()) => Ok(lease),
|
||||||
|
Err(TryLockError::WouldBlock) => Err(LiveSidecarError::ProfileDataDirectoryInUse {
|
||||||
|
path: profile_data_dir.to_path_buf(),
|
||||||
|
}),
|
||||||
|
Err(TryLockError::Error(error)) => Err(error.into()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn handle_request(
|
fn handle_request(
|
||||||
host: &mut SoftwareServoHost,
|
host: &mut SoftwareServoHost,
|
||||||
sessions: &mut HashMap<String, LiveSession>,
|
sessions: &mut HashMap<String, LiveSession>,
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
use std::io;
|
use std::{io, path::PathBuf};
|
||||||
|
|
||||||
use ely_servo_host::{
|
use ely_servo_host::{
|
||||||
ConsumedPermission, IOSurfaceHandle, RenderedFrame, ServoHostError, WebViewSnapshot,
|
ConsumedPermission, IOSurfaceHandle, RenderedFrame, ServoHostError, WebViewSnapshot,
|
||||||
@@ -305,6 +305,9 @@ pub(super) enum LiveSidecarError {
|
|||||||
#[error("sidecar process is already bound to profile {expected}; received {actual}")]
|
#[error("sidecar process is already bound to profile {expected}; received {actual}")]
|
||||||
ProfileMismatch { expected: String, actual: String },
|
ProfileMismatch { expected: String, actual: String },
|
||||||
|
|
||||||
|
#[error("servo profile data directory is already in use: {path}")]
|
||||||
|
ProfileDataDirectoryInUse { path: PathBuf },
|
||||||
|
|
||||||
#[error("{input} requires both x and y coordinates")]
|
#[error("{input} requires both x and y coordinates")]
|
||||||
IncompletePoint { input: &'static str },
|
IncompletePoint { input: &'static str },
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,9 @@
|
|||||||
|
|
||||||
use std::{
|
use std::{
|
||||||
error::Error,
|
error::Error,
|
||||||
io, thread,
|
io,
|
||||||
|
process::{Command, Stdio},
|
||||||
|
thread,
|
||||||
time::{Duration, Instant},
|
time::{Duration, Instant},
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -64,6 +66,38 @@ fn live_sidecar_streams_rgba_and_flushes_profile_storage_on_shutdown() -> Result
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn live_sidecar_leases_profile_data_directory_for_process_lifetime() -> Result<(), Box<dyn Error>> {
|
||||||
|
let root = TestDirectory::new()?;
|
||||||
|
let leased_dir = root.path().join("leased");
|
||||||
|
let independent_dir = root.path().join("independent");
|
||||||
|
let mut owner = Sidecar::spawn(&leased_dir)?;
|
||||||
|
assert!(leased_dir.join(".ely-servo-sidecar.lock").is_file());
|
||||||
|
|
||||||
|
let rejected = Command::new(env!("CARGO_BIN_EXE_ely_servo_sidecar"))
|
||||||
|
.arg("live")
|
||||||
|
.arg("--profile-data-dir")
|
||||||
|
.arg(&leased_dir)
|
||||||
|
.stdin(Stdio::null())
|
||||||
|
.stdout(Stdio::null())
|
||||||
|
.stderr(Stdio::piped())
|
||||||
|
.output()?;
|
||||||
|
let stderr = String::from_utf8(rejected.stderr)?;
|
||||||
|
assert!(!rejected.status.success(), "second sidecar unexpectedly acquired the profile lease");
|
||||||
|
assert!(
|
||||||
|
stderr.contains("ProfileDataDirectoryInUse"),
|
||||||
|
"second sidecar reported an unexpected error: {stderr}"
|
||||||
|
);
|
||||||
|
|
||||||
|
let mut independent = Sidecar::spawn(&independent_dir)?;
|
||||||
|
independent.shutdown()?;
|
||||||
|
owner.shutdown()?;
|
||||||
|
|
||||||
|
let mut replacement = Sidecar::spawn(&leased_dir)?;
|
||||||
|
replacement.shutdown()?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn servo_originated_history_url_does_not_trigger_a_second_navigation() -> Result<(), Box<dyn Error>>
|
fn servo_originated_history_url_does_not_trigger_a_second_navigation() -> Result<(), Box<dyn Error>>
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user