fix(servo): lease persistent profile data

This commit is contained in:
2026-07-09 23:05:10 -04:00
parent 62ee35a164
commit 755a6aabd8
3 changed files with 60 additions and 3 deletions
@@ -1,7 +1,8 @@
use std::{
collections::HashMap,
fs,
fs::{self, File, OpenOptions, TryLockError},
io::{self, BufRead},
path::Path,
};
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> {
let LiveArgs { profile_data_dir, rendering_context, iosurface_mach_service } = args;
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 {
SidecarRenderingContext::Software => RenderingContextKind::Software,
SidecarRenderingContext::Hardware => RenderingContextKind::Hardware,
@@ -84,6 +88,22 @@ pub(super) fn run(args: LiveArgs) -> Result<(), LiveSidecarError> {
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(
host: &mut SoftwareServoHost,
sessions: &mut HashMap<String, LiveSession>,
@@ -1,4 +1,4 @@
use std::io;
use std::{io, path::PathBuf};
use ely_servo_host::{
ConsumedPermission, IOSurfaceHandle, RenderedFrame, ServoHostError, WebViewSnapshot,
@@ -305,6 +305,9 @@ pub(super) enum LiveSidecarError {
#[error("sidecar process is already bound to profile {expected}; received {actual}")]
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")]
IncompletePoint { input: &'static str },
+35 -1
View File
@@ -2,7 +2,9 @@
use std::{
error::Error,
io, thread,
io,
process::{Command, Stdio},
thread,
time::{Duration, Instant},
};
@@ -64,6 +66,38 @@ fn live_sidecar_streams_rgba_and_flushes_profile_storage_on_shutdown() -> Result
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]
fn servo_originated_history_url_does_not_trigger_a_second_navigation() -> Result<(), Box<dyn Error>>
{