Make Git router teardown process-bounded
This commit is contained in:
parent
31e9ab0f2d
commit
e60baad993
5 changed files with 191 additions and 35 deletions
|
|
@ -25,6 +25,7 @@ use lazaret_core::records::{
|
||||||
SessionTerminalMessage, TerminalResize, TerminalSignal, TerminalSignalKind,
|
SessionTerminalMessage, TerminalResize, TerminalSignal, TerminalSignalKind,
|
||||||
};
|
};
|
||||||
use lazaret_host_coordinator::domain_store::{DomainStoreMutation, HostCoordinatorDomainStore};
|
use lazaret_host_coordinator::domain_store::{DomainStoreMutation, HostCoordinatorDomainStore};
|
||||||
|
use lazaret_host_coordinator::git_routing::GitRoutingCoordinator;
|
||||||
use lazaret_host_coordinator::network::NetworkCoordinator;
|
use lazaret_host_coordinator::network::NetworkCoordinator;
|
||||||
use lazaret_host_coordinator::runtime::{
|
use lazaret_host_coordinator::runtime::{
|
||||||
AwaitingAttachedRunsc, CommittedSandboxRuntime, SandboxCoordinator,
|
AwaitingAttachedRunsc, CommittedSandboxRuntime, SandboxCoordinator,
|
||||||
|
|
@ -42,10 +43,11 @@ use lazaret_linux::process::{
|
||||||
use lazaret_linux::user_namespace::UserNamespaceMap;
|
use lazaret_linux::user_namespace::UserNamespaceMap;
|
||||||
use lazaret_runtime_supervisor::sandbox::{
|
use lazaret_runtime_supervisor::sandbox::{
|
||||||
NETWORK_NAMESPACE_PATH, RootProcess, RunscCommand, SandboxBuildRequest, SandboxBundle,
|
NETWORK_NAMESPACE_PATH, RootProcess, RunscCommand, SandboxBuildRequest, SandboxBundle,
|
||||||
build_sandbox_bundle, default_sandbox_layout,
|
build_sandbox_bundle, build_sandbox_bundle_with_workspace, default_sandbox_layout,
|
||||||
};
|
};
|
||||||
use lazaret_runtime_supervisor::supervision::{
|
use lazaret_runtime_supervisor::supervision::{
|
||||||
AttachedRunscSignal, RuntimeNetworkLaunch, RuntimeSupervisorLaunch,
|
AttachedRunscSignal, RuntimeGitRoutingAuthority, RuntimeGitRoutingLaunch, RuntimeNetworkLaunch,
|
||||||
|
RuntimeSupervisorLaunch,
|
||||||
};
|
};
|
||||||
use rustix::process::Signal;
|
use rustix::process::Signal;
|
||||||
use tempfile::TempDir;
|
use tempfile::TempDir;
|
||||||
|
|
@ -250,6 +252,7 @@ fn run_matrix() -> Result<(), MatrixError> {
|
||||||
require_matrix_prerequisites()?;
|
require_matrix_prerequisites()?;
|
||||||
lost_acknowledgment_refuses_target_work()?;
|
lost_acknowledgment_refuses_target_work()?;
|
||||||
replaced_handoff_authority_refuses_target_work()?;
|
replaced_handoff_authority_refuses_target_work()?;
|
||||||
|
git_routing_clean_stop()?;
|
||||||
normal_stop_and_stop_resume()?;
|
normal_stop_and_stop_resume()?;
|
||||||
attached_runsc_loss_stops_guest()?;
|
attached_runsc_loss_stops_guest()?;
|
||||||
runtime_supervisor_loss_stops_guest()?;
|
runtime_supervisor_loss_stops_guest()?;
|
||||||
|
|
@ -622,11 +625,11 @@ mod network;
|
||||||
|
|
||||||
use fixtures::{Fixture, NetworkFixture};
|
use fixtures::{Fixture, NetworkFixture};
|
||||||
use handoff::{
|
use handoff::{
|
||||||
attached_runsc_loss_stops_guest, failure, host_coordinator_loss_stops_guest,
|
attached_runsc_loss_stops_guest, failure, git_routing_clean_stop,
|
||||||
lost_acknowledgment_refuses_target_work, matrix_io, normal_stop_and_stop_resume,
|
host_coordinator_loss_stops_guest, lost_acknowledgment_refuses_target_work, matrix_io,
|
||||||
replaced_handoff_authority_refuses_target_work, require_matrix_prerequisites,
|
normal_stop_and_stop_resume, replaced_handoff_authority_refuses_target_work,
|
||||||
run_handoff_matrix, run_host_coordinator_driver, run_network_cases,
|
require_matrix_prerequisites, run_handoff_matrix, run_host_coordinator_driver,
|
||||||
runtime_supervisor_loss_stops_guest,
|
run_network_cases, runtime_supervisor_loss_stops_guest,
|
||||||
};
|
};
|
||||||
use network::{
|
use network::{
|
||||||
hex, host_path, lock_file, networked_sandbox_view_isolated, run_sandbox_network_probe,
|
hex, host_path, lock_file, networked_sandbox_view_isolated, run_sandbox_network_probe,
|
||||||
|
|
|
||||||
|
|
@ -1,15 +1,17 @@
|
||||||
use super::{
|
use super::{
|
||||||
Arc, AwaitingAttachedRunsc, BENCHMARK_GUEST, BTreeMap, BundleDigest, CommittedSandboxRuntime,
|
Arc, AwaitingAttachedRunsc, BENCHMARK_GUEST, BTreeMap, BundleDigest, CommittedSandboxRuntime,
|
||||||
ConfigurationLoadRequest, ContainerId, CoordinatorId, Domain, DomainStoreMutation,
|
ConfigurationLoadRequest, ContainerId, CoordinatorId, Domain, DomainStoreMutation,
|
||||||
DurableDecision, Generation, GenerationId, HostCoordinatorDomainStore,
|
DurableDecision, File, Generation, GenerationId, GitRoutingCoordinator,
|
||||||
HostProcessOwnershipSlot, Ipv4Addr, MatrixError, NETWORK_NAMESPACE_PATH, NetworkCoordinator,
|
HostCoordinatorDomainStore, HostPath, HostProcessOwnershipSlot, Ipv4Addr, MatrixError,
|
||||||
NetworkSidecarId, Path, PathBuf, ProcessOwnershipContext, ResolvedDomainConfiguration,
|
NETWORK_NAMESPACE_PATH, NetworkCoordinator, NetworkSidecarId, Path, PathBuf,
|
||||||
RootProcess, RunscCommand, RuntimeNetworkLaunch, RuntimeSupervisorLaunch, SandboxBuildRequest,
|
ProcessOwnershipContext, ResolvedDomainConfiguration, RootProcess, RunscCommand,
|
||||||
SandboxBundle, SandboxCoordinator, SandboxId, SocketAddr, SocketAddrExt, TcpListener, TempDir,
|
RuntimeGitRoutingAuthority, RuntimeGitRoutingLaunch, RuntimeNetworkLaunch,
|
||||||
UnixListener, UserNamespaceMap, build_sandbox_bundle, current_mount_identity,
|
RuntimeSupervisorLaunch, SandboxBuildRequest, SandboxBundle, SandboxCoordinator, SandboxId,
|
||||||
current_process_identity, default_sandbox_layout, derive_ipv4_policy, failure, fs, hex,
|
SocketAddr, SocketAddrExt, TargetCommand, TcpListener, TempDir, UnixListener, UserNamespaceMap,
|
||||||
host_path, load_trusted_configuration, lock_file, stage_benchmark_rootfs_and_control,
|
build_sandbox_bundle, build_sandbox_bundle_with_workspace, child_broker,
|
||||||
stage_rootfs_and_control, try_exclusive_flock,
|
current_mount_identity, current_process_identity, default_sandbox_layout, derive_ipv4_policy,
|
||||||
|
failure, fs, hex, host_path, load_trusted_configuration, lock_file,
|
||||||
|
stage_benchmark_rootfs_and_control, stage_rootfs_and_control, try_exclusive_flock,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub(super) struct Fixture {
|
pub(super) struct Fixture {
|
||||||
|
|
@ -19,17 +21,24 @@ pub(super) struct Fixture {
|
||||||
pub(super) bundle: SandboxBundle,
|
pub(super) bundle: SandboxBundle,
|
||||||
pub(super) activity: PathBuf,
|
pub(super) activity: PathBuf,
|
||||||
pub(super) benchmark_results: Option<PathBuf>,
|
pub(super) benchmark_results: Option<PathBuf>,
|
||||||
|
git_routing: Option<GitRoutingFixture>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Fixture {
|
impl Fixture {
|
||||||
pub(super) fn new() -> Result<Self, MatrixError> {
|
pub(super) fn new() -> Result<Self, MatrixError> {
|
||||||
let tree = tempfile::tempdir()?;
|
let tree = tempfile::tempdir()?;
|
||||||
let root = tree.path().to_path_buf();
|
let root = tree.path().to_path_buf();
|
||||||
Self::build(&root, Some(tree))
|
Self::build(&root, Some(tree), false)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(super) fn new_git_routed() -> Result<Self, MatrixError> {
|
||||||
|
let tree = tempfile::tempdir()?;
|
||||||
|
let root = tree.path().to_path_buf();
|
||||||
|
Self::build(&root, Some(tree), true)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) fn in_directory(root: &Path) -> Result<Self, MatrixError> {
|
pub(super) fn in_directory(root: &Path) -> Result<Self, MatrixError> {
|
||||||
Self::build(root, None)
|
Self::build(root, None, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(clippy::too_many_arguments)]
|
#[allow(clippy::too_many_arguments)]
|
||||||
|
|
@ -136,16 +145,24 @@ impl Fixture {
|
||||||
bundle,
|
bundle,
|
||||||
workspace.join("activity"),
|
workspace.join("activity"),
|
||||||
Some(results),
|
Some(results),
|
||||||
|
None,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn build(root: &Path, tree: Option<TempDir>) -> Result<Self, MatrixError> {
|
fn build(
|
||||||
|
root: &Path,
|
||||||
|
tree: Option<TempDir>,
|
||||||
|
route_git_workspace: bool,
|
||||||
|
) -> Result<Self, MatrixError> {
|
||||||
let configuration_directory = root.join("configuration");
|
let configuration_directory = root.join("configuration");
|
||||||
let workspace = root.join("workspace");
|
let workspace = root.join("workspace");
|
||||||
let runtime = root.join("runtime");
|
let runtime = root.join("runtime");
|
||||||
fs::create_dir(&configuration_directory)?;
|
fs::create_dir(&configuration_directory)?;
|
||||||
fs::create_dir(&workspace)?;
|
fs::create_dir(&workspace)?;
|
||||||
fs::create_dir(&runtime)?;
|
fs::create_dir(&runtime)?;
|
||||||
|
let git_routing = route_git_workspace
|
||||||
|
.then(|| GitRoutingFixture::create(root, &workspace))
|
||||||
|
.transpose()?;
|
||||||
let configuration_path = configuration_directory.join("lazaret.toml");
|
let configuration_path = configuration_directory.join("lazaret.toml");
|
||||||
fs::write(
|
fs::write(
|
||||||
&configuration_path,
|
&configuration_path,
|
||||||
|
|
@ -180,14 +197,20 @@ impl Fixture {
|
||||||
.map_err(failure)?;
|
.map_err(failure)?;
|
||||||
let namespace =
|
let namespace =
|
||||||
lazaret_linux::filesystem::namespace_identity(Path::new(NETWORK_NAMESPACE_PATH))?;
|
lazaret_linux::filesystem::namespace_identity(Path::new(NETWORK_NAMESPACE_PATH))?;
|
||||||
let bundle = build_sandbox_bundle(SandboxBuildRequest {
|
let request = SandboxBuildRequest {
|
||||||
configuration: &configuration,
|
configuration: &configuration,
|
||||||
container_id,
|
container_id,
|
||||||
expected_network_namespace: namespace,
|
expected_network_namespace: namespace,
|
||||||
root_process,
|
root_process,
|
||||||
terminal: None,
|
terminal: None,
|
||||||
prepared_root: runtime_domain.join("prepared-root"),
|
prepared_root: runtime_domain.join("prepared-root"),
|
||||||
})
|
};
|
||||||
|
let bundle = match &git_routing {
|
||||||
|
Some(git_routing) => {
|
||||||
|
build_sandbox_bundle_with_workspace(request, git_routing.mountpoint.clone())
|
||||||
|
}
|
||||||
|
None => build_sandbox_bundle(request),
|
||||||
|
}
|
||||||
.map_err(failure)?;
|
.map_err(failure)?;
|
||||||
Self::finish_build(
|
Self::finish_build(
|
||||||
tree,
|
tree,
|
||||||
|
|
@ -195,6 +218,7 @@ impl Fixture {
|
||||||
bundle,
|
bundle,
|
||||||
workspace.join("activity"),
|
workspace.join("activity"),
|
||||||
None,
|
None,
|
||||||
|
git_routing,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -204,6 +228,7 @@ impl Fixture {
|
||||||
bundle: SandboxBundle,
|
bundle: SandboxBundle,
|
||||||
activity: PathBuf,
|
activity: PathBuf,
|
||||||
benchmark_results: Option<PathBuf>,
|
benchmark_results: Option<PathBuf>,
|
||||||
|
git_routing: Option<GitRoutingFixture>,
|
||||||
) -> Result<Self, MatrixError> {
|
) -> Result<Self, MatrixError> {
|
||||||
let runtime_domain = host_path(configuration.runtime_domain_root().canonical_label());
|
let runtime_domain = host_path(configuration.runtime_domain_root().canonical_label());
|
||||||
let container_id = ContainerId::new([6; 32]);
|
let container_id = ContainerId::new([6; 32]);
|
||||||
|
|
@ -252,6 +277,7 @@ impl Fixture {
|
||||||
bundle,
|
bundle,
|
||||||
activity,
|
activity,
|
||||||
benchmark_results,
|
benchmark_results,
|
||||||
|
git_routing,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -263,7 +289,7 @@ impl Fixture {
|
||||||
&self,
|
&self,
|
||||||
command: &RunscCommand,
|
command: &RunscCommand,
|
||||||
) -> Result<AwaitingAttachedRunsc, MatrixError> {
|
) -> Result<AwaitingAttachedRunsc, MatrixError> {
|
||||||
let launch = RuntimeSupervisorLaunch::from_runsc_command(
|
let mut launch = RuntimeSupervisorLaunch::from_runsc_command(
|
||||||
ProcessOwnershipContext {
|
ProcessOwnershipContext {
|
||||||
domain_id: self.configuration.domain_id(),
|
domain_id: self.configuration.domain_id(),
|
||||||
generation_id: GenerationId::new(7),
|
generation_id: GenerationId::new(7),
|
||||||
|
|
@ -271,10 +297,40 @@ impl Fixture {
|
||||||
slot: lazaret_core::records::HostProcessOwnershipSlot::SandboxRuntimeSupervisor,
|
slot: lazaret_core::records::HostProcessOwnershipSlot::SandboxRuntimeSupervisor,
|
||||||
},
|
},
|
||||||
command,
|
command,
|
||||||
)?
|
)?;
|
||||||
.with_user_namespace_map(UserNamespaceMap::resolve_current().map_err(failure)?)?;
|
if let Some(git_routing) = &self.git_routing {
|
||||||
AwaitingAttachedRunsc::launch(&SandboxCoordinator::new(&self.store), &launch)
|
launch = launch.with_git_routing(git_routing.launch()?)?;
|
||||||
.map_err(failure)
|
}
|
||||||
|
launch = launch
|
||||||
|
.with_user_namespace_map(UserNamespaceMap::resolve_current().map_err(failure)?)?;
|
||||||
|
let mut pending =
|
||||||
|
AwaitingAttachedRunsc::launch(&SandboxCoordinator::new(&self.store), &launch)
|
||||||
|
.map_err(failure)?;
|
||||||
|
if let Some(git_routing) = &self.git_routing {
|
||||||
|
let coordinator = GitRoutingCoordinator::new(&self.store);
|
||||||
|
coordinator
|
||||||
|
.begin_intent(
|
||||||
|
GenerationId::new(7),
|
||||||
|
HostPath::new(
|
||||||
|
git_routing
|
||||||
|
.mountpoint
|
||||||
|
.as_os_str()
|
||||||
|
.as_encoded_bytes()
|
||||||
|
.to_vec(),
|
||||||
|
),
|
||||||
|
HostPath::new(
|
||||||
|
git_routing
|
||||||
|
.workspace
|
||||||
|
.as_os_str()
|
||||||
|
.as_encoded_bytes()
|
||||||
|
.to_vec(),
|
||||||
|
),
|
||||||
|
HostPath::new(git_routing.isolated.as_os_str().as_encoded_bytes().to_vec()),
|
||||||
|
)
|
||||||
|
.map_err(failure)?;
|
||||||
|
pending.start_git_routing(&coordinator).map_err(failure)?;
|
||||||
|
}
|
||||||
|
Ok(pending)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) fn alternate_bundle(&self) -> Result<SandboxBundle, MatrixError> {
|
pub(super) fn alternate_bundle(&self) -> Result<SandboxBundle, MatrixError> {
|
||||||
|
|
@ -316,6 +372,68 @@ impl Fixture {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct GitRoutingFixture {
|
||||||
|
workspace: PathBuf,
|
||||||
|
isolated: PathBuf,
|
||||||
|
mountpoint: PathBuf,
|
||||||
|
git_common: PathBuf,
|
||||||
|
transient_hooks: PathBuf,
|
||||||
|
transient_config: PathBuf,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl GitRoutingFixture {
|
||||||
|
fn create(root: &Path, workspace: &Path) -> Result<Self, MatrixError> {
|
||||||
|
child_broker()
|
||||||
|
.run_transient(
|
||||||
|
&TargetCommand::new("git")
|
||||||
|
.argument("init")
|
||||||
|
.argument("--quiet")
|
||||||
|
.argument("--initial-branch=main")
|
||||||
|
.argument(workspace),
|
||||||
|
)
|
||||||
|
.map_err(failure)?;
|
||||||
|
let routing = root.join("git-routing");
|
||||||
|
let isolated = routing.join("isolated");
|
||||||
|
let mountpoint = routing.join("workspace");
|
||||||
|
let transient_hooks = routing.join("hooks");
|
||||||
|
let transient_config = routing.join("config");
|
||||||
|
for directory in [&isolated, &mountpoint, &transient_hooks] {
|
||||||
|
fs::create_dir_all(directory)?;
|
||||||
|
}
|
||||||
|
fs::write(&transient_config, b"")?;
|
||||||
|
Ok(Self {
|
||||||
|
workspace: workspace.to_path_buf(),
|
||||||
|
isolated,
|
||||||
|
mountpoint,
|
||||||
|
git_common: workspace.join(".git"),
|
||||||
|
transient_hooks,
|
||||||
|
transient_config,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn launch(&self) -> Result<RuntimeGitRoutingLaunch, MatrixError> {
|
||||||
|
RuntimeGitRoutingLaunch::new(RuntimeGitRoutingAuthority {
|
||||||
|
workspace: File::open(&self.workspace)?,
|
||||||
|
workspace_label: self.workspace.clone(),
|
||||||
|
isolated: File::open(&self.isolated)?,
|
||||||
|
mountpoint: File::open(&self.mountpoint)?,
|
||||||
|
mountpoint_label: self.mountpoint.clone(),
|
||||||
|
git_common: File::open(&self.git_common)?,
|
||||||
|
git_common_label: self.git_common.clone(),
|
||||||
|
transient_hooks: File::open(&self.transient_hooks)?,
|
||||||
|
transient_hooks_label: self.transient_hooks.clone(),
|
||||||
|
transient_config: File::options()
|
||||||
|
.read(true)
|
||||||
|
.write(true)
|
||||||
|
.open(&self.transient_config)?,
|
||||||
|
transient_config_label: self.transient_config.clone(),
|
||||||
|
global_excludes: None,
|
||||||
|
isolate_ignored: true,
|
||||||
|
})
|
||||||
|
.map_err(failure)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub(super) struct NetworkFixture {
|
pub(super) struct NetworkFixture {
|
||||||
_tree: TempDir,
|
_tree: TempDir,
|
||||||
_host_loopback: TcpListener,
|
_host_loopback: TcpListener,
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,11 @@
|
||||||
use super::{
|
use super::{
|
||||||
AttachedRunscSignal, CoordinatorId, Duration, Fixture, GenerationId, HOST_COORDINATOR_DRIVER,
|
AttachedRunscSignal, CoordinatorId, Duration, Fixture, GenerationId, GitRoutingCoordinator,
|
||||||
HostProcessOwnershipSlot, MatrixError, ParticipantState, Path, PathBuf, PidfsProcessIdentityV1,
|
HOST_COORDINATOR_DRIVER, HostProcessOwnershipSlot, MatrixError, ParticipantRole,
|
||||||
PlatformObservation, ProcessOwnershipCommitAck, ProcessOwnershipContext, RetainedProcess,
|
ParticipantState, Path, PathBuf, PidfsProcessIdentityV1, PlatformObservation,
|
||||||
SandboxCoordinator, Signal, TargetCommand, UnixListener, check_platform, child_broker,
|
ProcessOwnershipCommitAck, ProcessOwnershipContext, RetainedProcess, SandboxCoordinator,
|
||||||
current_process_identity, fs, host_path, networked_sandbox_view_isolated, read_start_time,
|
Signal, TargetCommand, UnixListener, check_platform, child_broker, current_process_identity,
|
||||||
sandbox_participant, thread, unreachable_permitted_destination_does_not_block_start,
|
fs, host_path, networked_sandbox_view_isolated, read_start_time, sandbox_participant, thread,
|
||||||
|
unreachable_permitted_destination_does_not_block_start,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub(super) fn run_handoff_matrix() -> Result<(), MatrixError> {
|
pub(super) fn run_handoff_matrix() -> Result<(), MatrixError> {
|
||||||
|
|
@ -175,6 +176,32 @@ pub(super) fn normal_stop_and_stop_resume() -> Result<(), MatrixError> {
|
||||||
assert_activity_stable(&fixture.activity)
|
assert_activity_stable(&fixture.activity)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(super) fn git_routing_clean_stop() -> Result<(), MatrixError> {
|
||||||
|
let fixture = Fixture::new_git_routed()?;
|
||||||
|
let mut runtime = fixture.launch_committed()?;
|
||||||
|
wait_for_activity(&fixture.activity)?;
|
||||||
|
runtime
|
||||||
|
.stop_sandbox(&SandboxCoordinator::new(&fixture.store))
|
||||||
|
.map_err(failure)?;
|
||||||
|
runtime
|
||||||
|
.stop_git_routing(&GitRoutingCoordinator::new(&fixture.store))
|
||||||
|
.map_err(failure)?;
|
||||||
|
runtime.graceful_exit().map_err(failure)?;
|
||||||
|
let snapshot = fixture.store.snapshot().map_err(failure)?;
|
||||||
|
for role in [ParticipantRole::Sandbox, ParticipantRole::GitRouting] {
|
||||||
|
assert_eq!(
|
||||||
|
snapshot
|
||||||
|
.participants
|
||||||
|
.iter()
|
||||||
|
.find(|participant| participant.role() == role)
|
||||||
|
.ok_or_else(|| failure(format!("{role:?} participant is absent")))?
|
||||||
|
.state(),
|
||||||
|
ParticipantState::Clean
|
||||||
|
);
|
||||||
|
}
|
||||||
|
assert_activity_stable(&fixture.activity)
|
||||||
|
}
|
||||||
|
|
||||||
pub(super) fn attached_runsc_loss_stops_guest() -> Result<(), MatrixError> {
|
pub(super) fn attached_runsc_loss_stops_guest() -> Result<(), MatrixError> {
|
||||||
let fixture = Fixture::new()?;
|
let fixture = Fixture::new()?;
|
||||||
let mut runtime = fixture.launch_committed()?;
|
let mut runtime = fixture.launch_committed()?;
|
||||||
|
|
|
||||||
|
|
@ -202,11 +202,12 @@ impl IgnoredWorkspace {
|
||||||
&mount_config(configuration.threads),
|
&mount_config(configuration.threads),
|
||||||
)?;
|
)?;
|
||||||
if let Err(error) = ready() {
|
if let Err(error) = ready() {
|
||||||
let _ = session.umount_and_join();
|
drop(session);
|
||||||
return Err(error);
|
return Err(error);
|
||||||
}
|
}
|
||||||
std::io::copy(&mut std::io::stdin().lock(), &mut std::io::sink())?;
|
std::io::copy(&mut std::io::stdin().lock(), &mut std::io::sink())?;
|
||||||
session.umount_and_join()
|
drop(session);
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn root(&self, backing: Classification) -> &BackingRoot {
|
fn root(&self, backing: Classification) -> &BackingRoot {
|
||||||
|
|
|
||||||
|
|
@ -7,10 +7,17 @@ use fuser::{Config, LockOwner, MountOption};
|
||||||
use nix::fcntl::{FcntlArg, fcntl};
|
use nix::fcntl::{FcntlArg, fcntl};
|
||||||
|
|
||||||
use super::nodes::{OpenFile, fuse_lock, record_lock};
|
use super::nodes::{OpenFile, fuse_lock, record_lock};
|
||||||
use super::{Classification, IgnoredWorkspace};
|
use super::{Classification, IgnoredWorkspace, mount_config};
|
||||||
|
|
||||||
static SEQUENCE: AtomicU64 = AtomicU64::new(0);
|
static SEQUENCE: AtomicU64 = AtomicU64::new(0);
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn multithreaded_router_uses_independent_fuse_channels() {
|
||||||
|
let config = mount_config(8);
|
||||||
|
assert_eq!(config.n_threads, Some(8));
|
||||||
|
assert!(config.clone_fd);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn posix_lock_owners_use_distinct_backing_lock_domains() {
|
fn posix_lock_owners_use_distinct_backing_lock_domains() {
|
||||||
let fixture = Fixture::new();
|
let fixture = Fixture::new();
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue