diff --git a/src/deb/ephemeral.rs b/src/deb/ephemeral.rs index ab0ac21..c56ce52 100644 --- a/src/deb/ephemeral.rs +++ b/src/deb/ephemeral.rs @@ -4,6 +4,7 @@ use directories::ProjectDirs; use std::error::Error; use std::fs; use std::path::{Path, PathBuf}; +use std::sync::Arc; use tar::Archive; use xz2::read::XzDecoder; @@ -25,8 +26,12 @@ impl EphemeralContextGuard { pub async fn new(series: &str, arch: Option<&str>) -> Result> { let current_context_name = context::manager().current_name(); + // Capture the current context once to avoid race conditions + // with other threads modifying the global context state + let ctx = context::current(); + // Create a temporary directory for the chroot - let chroot_path_str = context::current().create_temp_dir()?; + let chroot_path_str = ctx.create_temp_dir()?; let chroot_path = PathBuf::from(chroot_path_str); log::debug!( @@ -37,7 +42,7 @@ impl EphemeralContextGuard { ); // Download and extract the chroot tarball - Self::download_and_extract_chroot(series, arch, &chroot_path).await?; + Self::download_and_extract_chroot(series, arch, &chroot_path, ctx.clone()).await?; // Switch to an ephemeral context to build the package in the chroot context::manager().set_current_ephemeral(Context::new(ContextConfig::Unshare { @@ -56,7 +61,10 @@ impl EphemeralContextGuard { series: &str, arch: Option<&str>, chroot_path: &PathBuf, + ctx: Arc, ) -> Result<(), Box> { + // Clone ctx for use in create_device_nodes after download_chroot_tarball consumes it + let ctx_for_devices = ctx.clone(); // Get project directories for caching let proj_dirs = ProjectDirs::from("com", "pkh", "pkh") .ok_or("Could not determine project directories")?; @@ -74,7 +82,6 @@ impl EphemeralContextGuard { // Check for existing lockfile, and wait for a timeout if it exists // After timeout, warn the user let lockfile_path = tarball_path.with_extension("lock"); - let ctx = context::current(); // Check if lockfile exists and wait for it to be removed let mut wait_time = 0; @@ -110,7 +117,7 @@ impl EphemeralContextGuard { series, arch ); - Self::download_chroot_tarball(series, arch, &tarball_path).await?; + Self::download_chroot_tarball(series, arch, &tarball_path, ctx).await?; } else { log::debug!( "Using cached chroot tarball for {} (arch: {:?})", @@ -125,7 +132,7 @@ impl EphemeralContextGuard { // Create device nodes in the chroot log::debug!("Creating device nodes in chroot..."); - Self::create_device_nodes(chroot_path)?; + Self::create_device_nodes(chroot_path, ctx_for_devices)?; Ok(()) } @@ -134,8 +141,8 @@ impl EphemeralContextGuard { series: &str, arch: Option<&str>, tarball_path: &Path, + ctx: Arc, ) -> Result<(), Box> { - let ctx = context::current(); // Create a lock file to make sure that noone tries to use the file while it's not fully downloaded let lockfile_path = tarball_path.with_extension("lock"); @@ -218,8 +225,7 @@ impl EphemeralContextGuard { Ok(()) } - fn create_device_nodes(chroot_path: &Path) -> Result<(), Box> { - let ctx = context::current(); + fn create_device_nodes(chroot_path: &Path, ctx: Arc) -> Result<(), Box> { let dev_null_path = chroot_path.join("dev/null"); let dev_zero_path = chroot_path.join("dev/zero");