From edd09ad4e07ae2ad8aa42ec99342a1c48eb9e9e9 Mon Sep 17 00:00:00 2001 From: Bas Zalmstra <4995967+baszalmstra@users.noreply.github.com> Date: Fri, 5 Sep 2025 15:53:11 +0200 Subject: [PATCH 01/13] fix: clear filesystem cache --- .../src/command_dispatcher/mod.rs | 21 +++++++ .../src/command_dispatcher_processor/mod.rs | 11 ++++ .../src/discover_backend_cache.rs | 5 ++ .../tests/integration/main.rs | 62 ++++++++++++++++++- crates/pixi_glob/src/glob_hash_cache.rs | 5 ++ 5 files changed, 102 insertions(+), 2 deletions(-) diff --git a/crates/pixi_command_dispatcher/src/command_dispatcher/mod.rs b/crates/pixi_command_dispatcher/src/command_dispatcher/mod.rs index a8fb04001a..33db658f84 100644 --- a/crates/pixi_command_dispatcher/src/command_dispatcher/mod.rs +++ b/crates/pixi_command_dispatcher/src/command_dispatcher/mod.rs @@ -236,6 +236,8 @@ pub(crate) enum ForegroundMessage { InstallPixiEnvironment(InstallPixiEnvironmentTask), InstantiateToolEnvironment(Task), ClearReporter(oneshot::Sender<()>), + #[from(ignore)] + ClearSourceBuildCacheStatusCache(oneshot::Sender<()>), } /// A message that is send to the background task to start solving a particular @@ -361,6 +363,25 @@ impl CommandDispatcher { &self.data.discovery_cache } + /// Clears in-memory caches whose correctness depends on the filesystem. + /// + /// This invalidates memoized results that are derived from files on disk so + /// subsequent operations re-check the current state of the filesystem. It: + /// - clears glob hash memoization (`GlobHashCache`) used for input file hashing + /// - clears memoized SourceBuildCacheStatus results held by the processor, + /// while preserving any in-flight queries + pub async fn clear_filesystem_caches(&self) { + // These caches are process-local and safe to clear from any dispatcher clone. + self.data.glob_hash_cache.clear(); + + // Ask the processor to drop memoized SourceBuildCacheStatus results. + if let Some(sender) = self.channel().sender() { + let (tx, rx) = oneshot::channel(); + let _ = sender.send(ForegroundMessage::ClearSourceBuildCacheStatusCache(tx)); + let _ = rx.await; + } + } + /// Returns the download client used by the command dispatcher. pub fn download_client(&self) -> &ClientWithMiddleware { &self.data.download_client diff --git a/crates/pixi_command_dispatcher/src/command_dispatcher_processor/mod.rs b/crates/pixi_command_dispatcher/src/command_dispatcher_processor/mod.rs index 6f401f9d90..447664cde2 100644 --- a/crates/pixi_command_dispatcher/src/command_dispatcher_processor/mod.rs +++ b/crates/pixi_command_dispatcher/src/command_dispatcher_processor/mod.rs @@ -391,6 +391,9 @@ impl CommandDispatcherProcessor { self.on_source_build_cache_status(task) } ForegroundMessage::ClearReporter(sender) => self.clear_reporter(sender), + ForegroundMessage::ClearSourceBuildCacheStatusCache(sender) => { + self.clear_source_build_cache_status_cache(sender) + } ForegroundMessage::SourceMetadata(task) => self.on_source_metadata(task), ForegroundMessage::BackendSourceBuild(task) => self.on_backend_source_build(task), } @@ -556,6 +559,14 @@ impl CommandDispatcherProcessor { let _ = sender.send(()); } + /// Clears cached results for source_build_cache_status, preserving in-flight tasks. + fn clear_source_build_cache_status_cache(&mut self, sender: oneshot::Sender<()>) { + self.source_build_cache_status + .retain(|_, v| matches!(v, PendingDeduplicatingTask::Pending(_, _))); + // Keep ids map so subsequent identical specs reuse their id; this is harmless. + let _ = sender.send(()); + } + /// Returns true if by following the parent chain of the `parent` context we /// stumble on `id`. pub fn contains_cycle + PartialEq>( diff --git a/crates/pixi_command_dispatcher/src/discover_backend_cache.rs b/crates/pixi_command_dispatcher/src/discover_backend_cache.rs index 00f57241db..b793446bca 100644 --- a/crates/pixi_command_dispatcher/src/discover_backend_cache.rs +++ b/crates/pixi_command_dispatcher/src/discover_backend_cache.rs @@ -78,4 +78,9 @@ impl DiscoveryCache { } } } + + // Note: we intentionally do not implement a clear() here because the + // underlying coalesced map does not expose a general clear operation. + // Callers that need to invalidate discovery results should bump their + // cache key inputs or recreate the cache instance at construction time. } diff --git a/crates/pixi_command_dispatcher/tests/integration/main.rs b/crates/pixi_command_dispatcher/tests/integration/main.rs index 8d2f68ef4a..923790abf1 100644 --- a/crates/pixi_command_dispatcher/tests/integration/main.rs +++ b/crates/pixi_command_dispatcher/tests/integration/main.rs @@ -14,14 +14,17 @@ use pixi_build_frontend::{ }; use pixi_command_dispatcher::{ BuildEnvironment, CacheDirs, CommandDispatcher, Executor, InstallPixiEnvironmentSpec, - InstantiateToolEnvironmentSpec, PixiEnvironmentSpec, + InstantiateToolEnvironmentSpec, PackageIdentifier, PixiEnvironmentSpec, + SourceBuildCacheStatusSpec, }; use pixi_config::default_channel_config; +use pixi_record::PinnedPathSpec; use pixi_spec::{GitReference, GitSpec, PathSpec, PixiSpec}; use pixi_spec_containers::DependencyMap; use pixi_test_utils::format_diagnostic; use rattler_conda_types::{ - GenericVirtualPackage, PackageName, Platform, VersionSpec, prefix::Prefix, + ChannelUrl, GenericVirtualPackage, PackageName, Platform, VersionSpec, VersionWithSource, + prefix::Prefix, }; use rattler_virtual_packages::{VirtualPackageOverrides, VirtualPackages}; use url::Url; @@ -533,3 +536,58 @@ pub async fn instantiate_backend_with_from_source() { insta::assert_debug_snapshot!(err); } + +#[tokio::test] +async fn source_build_cache_status_clear_works() { + let tmp_dir = tempfile::tempdir().unwrap(); + + let dispatcher = CommandDispatcher::builder() + .with_cache_dirs(CacheDirs::new(tmp_dir.path().to_path_buf())) + .finish(); + + let host = Platform::current(); + let build_env = BuildEnvironment { + host_platform: host, + build_platform: host, + build_virtual_packages: vec![], + host_virtual_packages: vec![], + }; + + let pkg = PackageIdentifier { + name: PackageName::try_from("dummy-pkg").unwrap(), + version: VersionWithSource::from_str("0.0.0").unwrap(), + build: "0".to_string(), + subdir: host.to_string(), + }; + + let spec = SourceBuildCacheStatusSpec { + package: pkg, + source: PinnedPathSpec { + path: tmp_dir.path().to_string_lossy().into_owned().into(), + } + .into(), + channels: Vec::::new(), + build_environment: build_env, + }; + + let first = dispatcher + .source_build_cache_status(spec.clone()) + .await + .expect("query succeeds"); + let second = dispatcher + .source_build_cache_status(spec.clone()) + .await + .expect("query succeeds"); + + // Cached result should return the same Arc + assert!(std::sync::Arc::ptr_eq(&first, &second)); + + // Clear and expect a fresh Arc on next query + dispatcher.clear_filesystem_caches().await; + + let third = dispatcher + .source_build_cache_status(spec) + .await + .expect("query succeeds"); + assert!(!std::sync::Arc::ptr_eq(&first, &third)); +} diff --git a/crates/pixi_glob/src/glob_hash_cache.rs b/crates/pixi_glob/src/glob_hash_cache.rs index d7fcd32ca9..d761897ce6 100644 --- a/crates/pixi_glob/src/glob_hash_cache.rs +++ b/crates/pixi_glob/src/glob_hash_cache.rs @@ -129,4 +129,9 @@ impl GlobHashCache { } } } + + /// Clears all memoized glob hashes. In-flight computations are unaffected. + pub fn clear(&self) { + self.cache.clear(); + } } From bb796d7e4d251dcc35291b523c135fe049fdb4c3 Mon Sep 17 00:00:00 2001 From: Bas Zalmstra <4995967+baszalmstra@users.noreply.github.com> Date: Fri, 5 Sep 2025 16:33:43 +0200 Subject: [PATCH 02/13] fix: clear filesystem cache --- crates/pixi_cli/src/run.rs | 3 +++ .../src/command_dispatcher/mod.rs | 8 ++------ .../src/command_dispatcher_processor/mod.rs | 13 ++++++++----- 3 files changed, 13 insertions(+), 11 deletions(-) diff --git a/crates/pixi_cli/src/run.rs b/crates/pixi_cli/src/run.rs index 31dc7ab19f..9635b66c9b 100644 --- a/crates/pixi_cli/src/run.rs +++ b/crates/pixi_cli/src/run.rs @@ -266,6 +266,9 @@ pub async fn execute(args: Args) -> miette::Result<()> { // Clear the current progress reports. lock_file.command_dispatcher.clear_reporter().await; + // Clear caches based on the filesystem. The tasks might change files on disk. + lock_file.command_dispatcher.clear_filesystem_caches().await; + let command_env = get_task_env( &executable_task.run_environment, args.clean_env || executable_task.task().clean_env(), diff --git a/crates/pixi_command_dispatcher/src/command_dispatcher/mod.rs b/crates/pixi_command_dispatcher/src/command_dispatcher/mod.rs index 33db658f84..fda7f1b932 100644 --- a/crates/pixi_command_dispatcher/src/command_dispatcher/mod.rs +++ b/crates/pixi_command_dispatcher/src/command_dispatcher/mod.rs @@ -237,7 +237,7 @@ pub(crate) enum ForegroundMessage { InstantiateToolEnvironment(Task), ClearReporter(oneshot::Sender<()>), #[from(ignore)] - ClearSourceBuildCacheStatusCache(oneshot::Sender<()>), + ClearFilesystemCaches(oneshot::Sender<()>), } /// A message that is send to the background task to start solving a particular @@ -371,13 +371,9 @@ impl CommandDispatcher { /// - clears memoized SourceBuildCacheStatus results held by the processor, /// while preserving any in-flight queries pub async fn clear_filesystem_caches(&self) { - // These caches are process-local and safe to clear from any dispatcher clone. - self.data.glob_hash_cache.clear(); - - // Ask the processor to drop memoized SourceBuildCacheStatus results. if let Some(sender) = self.channel().sender() { let (tx, rx) = oneshot::channel(); - let _ = sender.send(ForegroundMessage::ClearSourceBuildCacheStatusCache(tx)); + let _ = sender.send(ForegroundMessage::ClearFilesystemCaches(tx)); let _ = rx.await; } } diff --git a/crates/pixi_command_dispatcher/src/command_dispatcher_processor/mod.rs b/crates/pixi_command_dispatcher/src/command_dispatcher_processor/mod.rs index 447664cde2..05edae8843 100644 --- a/crates/pixi_command_dispatcher/src/command_dispatcher_processor/mod.rs +++ b/crates/pixi_command_dispatcher/src/command_dispatcher_processor/mod.rs @@ -391,8 +391,8 @@ impl CommandDispatcherProcessor { self.on_source_build_cache_status(task) } ForegroundMessage::ClearReporter(sender) => self.clear_reporter(sender), - ForegroundMessage::ClearSourceBuildCacheStatusCache(sender) => { - self.clear_source_build_cache_status_cache(sender) + ForegroundMessage::ClearFilesystemCaches(sender) => { + self.clear_filesystem_caches(sender) } ForegroundMessage::SourceMetadata(task) => self.on_source_metadata(task), ForegroundMessage::BackendSourceBuild(task) => self.on_backend_source_build(task), @@ -559,11 +559,14 @@ impl CommandDispatcherProcessor { let _ = sender.send(()); } - /// Clears cached results for source_build_cache_status, preserving in-flight tasks. - fn clear_source_build_cache_status_cache(&mut self, sender: oneshot::Sender<()>) { + /// Clears cached results based on the filesystem, preserving in-flight tasks. + fn clear_filesystem_caches(&mut self, sender: oneshot::Sender<()>) { + self.inner.glob_hash_cache.clear(); + + // Clear source build cache status, preserving in-flight tasks. self.source_build_cache_status .retain(|_, v| matches!(v, PendingDeduplicatingTask::Pending(_, _))); - // Keep ids map so subsequent identical specs reuse their id; this is harmless. + let _ = sender.send(()); } From 99b17e9f18575ffeb924a0ea139ae7805b4e4afc Mon Sep 17 00:00:00 2001 From: Bas Zalmstra <4995967+baszalmstra@users.noreply.github.com> Date: Fri, 5 Sep 2025 16:39:45 +0200 Subject: [PATCH 03/13] fix: remove unused comment --- crates/pixi_command_dispatcher/src/discover_backend_cache.rs | 5 ----- 1 file changed, 5 deletions(-) diff --git a/crates/pixi_command_dispatcher/src/discover_backend_cache.rs b/crates/pixi_command_dispatcher/src/discover_backend_cache.rs index b793446bca..00f57241db 100644 --- a/crates/pixi_command_dispatcher/src/discover_backend_cache.rs +++ b/crates/pixi_command_dispatcher/src/discover_backend_cache.rs @@ -78,9 +78,4 @@ impl DiscoveryCache { } } } - - // Note: we intentionally do not implement a clear() here because the - // underlying coalesced map does not expose a general clear operation. - // Callers that need to invalidate discovery results should bump their - // cache key inputs or recreate the cache instance at construction time. } From 4bd1a67058c15f4e48e9c69b0adc9f41ed458d6c Mon Sep 17 00:00:00 2001 From: Bas Zalmstra <4995967+baszalmstra@users.noreply.github.com> Date: Fri, 5 Sep 2025 16:47:40 +0200 Subject: [PATCH 04/13] fix: merge issue --- crates/pixi_command_dispatcher/tests/integration/main.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/crates/pixi_command_dispatcher/tests/integration/main.rs b/crates/pixi_command_dispatcher/tests/integration/main.rs index 923790abf1..1f9a04369d 100644 --- a/crates/pixi_command_dispatcher/tests/integration/main.rs +++ b/crates/pixi_command_dispatcher/tests/integration/main.rs @@ -568,6 +568,8 @@ async fn source_build_cache_status_clear_works() { .into(), channels: Vec::::new(), build_environment: build_env, + channel_config: default_channel_config(), + enabled_protocols: Default::default(), }; let first = dispatcher From 294dbef84e6fef456496a0bee0d3712a5c50b808 Mon Sep 17 00:00:00 2001 From: nichmor Date: Wed, 10 Sep 2025 16:05:50 +0300 Subject: [PATCH 05/13] fix: deadlock in the test --- .../tests/integration/main.rs | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/crates/pixi_command_dispatcher/tests/integration/main.rs b/crates/pixi_command_dispatcher/tests/integration/main.rs index 1f9a04369d..c858549576 100644 --- a/crates/pixi_command_dispatcher/tests/integration/main.rs +++ b/crates/pixi_command_dispatcher/tests/integration/main.rs @@ -584,6 +584,14 @@ async fn source_build_cache_status_clear_works() { // Cached result should return the same Arc assert!(std::sync::Arc::ptr_eq(&first, &second)); + // save address so we can compare them later + let first_address = format!("{:p}", first); + + // now drop the cached entries to release the Arc + // which will unlock the fd locks that we hold on the cache files + drop(first); + drop(second); + // Clear and expect a fresh Arc on next query dispatcher.clear_filesystem_caches().await; @@ -591,5 +599,10 @@ async fn source_build_cache_status_clear_works() { .source_build_cache_status(spec) .await .expect("query succeeds"); - assert!(!std::sync::Arc::ptr_eq(&first, &third)); + + let third_address = format!("{:p}", third); + assert_ne!( + first_address, third_address, + "expected different Arc addresses" + ); } From 8f80fec206c9a23e6fe43d6adf5eed7055f3b78c Mon Sep 17 00:00:00 2001 From: nichmor Date: Thu, 11 Sep 2025 18:29:04 +0300 Subject: [PATCH 06/13] misc: add some sleep on windows --- crates/pixi_command_dispatcher/tests/integration/main.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/crates/pixi_command_dispatcher/tests/integration/main.rs b/crates/pixi_command_dispatcher/tests/integration/main.rs index c858549576..7ab77f0fb4 100644 --- a/crates/pixi_command_dispatcher/tests/integration/main.rs +++ b/crates/pixi_command_dispatcher/tests/integration/main.rs @@ -592,6 +592,10 @@ async fn source_build_cache_status_clear_works() { drop(first); drop(second); + #[cfg(windows)] + // testing the theory of "drop releases the lock" is hard on windows + tokio::time::sleep(tokio::time::Duration::from_secs(3)).await; + // Clear and expect a fresh Arc on next query dispatcher.clear_filesystem_caches().await; From 81aba296c6d5c8209e2a311d26ac2f103b86b202 Mon Sep 17 00:00:00 2001 From: nichmor Date: Fri, 12 Sep 2025 14:14:36 +0300 Subject: [PATCH 07/13] misc: debug the windows test --- .../tests/integration/main.rs | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/crates/pixi_command_dispatcher/tests/integration/main.rs b/crates/pixi_command_dispatcher/tests/integration/main.rs index 7ab77f0fb4..371bb2e583 100644 --- a/crates/pixi_command_dispatcher/tests/integration/main.rs +++ b/crates/pixi_command_dispatcher/tests/integration/main.rs @@ -4,6 +4,7 @@ mod event_tree; use std::{ collections::HashMap, path::{Path, PathBuf}, + ptr, str::FromStr, }; @@ -584,17 +585,23 @@ async fn source_build_cache_status_clear_works() { // Cached result should return the same Arc assert!(std::sync::Arc::ptr_eq(&first, &second)); + // assert!(ptr::eq(&first, &second)); + // save address so we can compare them later let first_address = format!("{:p}", first); + let second_address = format!("{:p}", second); + + eprintln!("first address: {first_address}"); + eprintln!("second address: {second_address}"); // now drop the cached entries to release the Arc // which will unlock the fd locks that we hold on the cache files drop(first); drop(second); - #[cfg(windows)] - // testing the theory of "drop releases the lock" is hard on windows - tokio::time::sleep(tokio::time::Duration::from_secs(3)).await; + // #[cfg(windows)] + // // testing the theory of "drop releases the lock" is hard on windows + // tokio::time::sleep(tokio::time::Duration::from_secs(3)).await; // Clear and expect a fresh Arc on next query dispatcher.clear_filesystem_caches().await; @@ -605,6 +612,9 @@ async fn source_build_cache_status_clear_works() { .expect("query succeeds"); let third_address = format!("{:p}", third); + + eprintln!("third address: {third_address}"); + assert_ne!( first_address, third_address, "expected different Arc addresses" From ea090d1179a16a15df1fc2e55f246b8531e04a03 Mon Sep 17 00:00:00 2001 From: nichmor Date: Fri, 12 Sep 2025 14:23:59 +0300 Subject: [PATCH 08/13] misc: debug the windows test --- crates/pixi_command_dispatcher/tests/integration/main.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/pixi_command_dispatcher/tests/integration/main.rs b/crates/pixi_command_dispatcher/tests/integration/main.rs index 371bb2e583..8c3d9b948e 100644 --- a/crates/pixi_command_dispatcher/tests/integration/main.rs +++ b/crates/pixi_command_dispatcher/tests/integration/main.rs @@ -4,7 +4,7 @@ mod event_tree; use std::{ collections::HashMap, path::{Path, PathBuf}, - ptr, + // ptr, str::FromStr, }; From 7ed9ae168bb6e49f0410d6ae0603babf7483ec67 Mon Sep 17 00:00:00 2001 From: nichmor Date: Fri, 12 Sep 2025 15:25:35 +0300 Subject: [PATCH 09/13] misc: fail the test --- crates/pixi_command_dispatcher/tests/integration/main.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/crates/pixi_command_dispatcher/tests/integration/main.rs b/crates/pixi_command_dispatcher/tests/integration/main.rs index 8c3d9b948e..2357a9994f 100644 --- a/crates/pixi_command_dispatcher/tests/integration/main.rs +++ b/crates/pixi_command_dispatcher/tests/integration/main.rs @@ -619,4 +619,6 @@ async fn source_build_cache_status_clear_works() { first_address, third_address, "expected different Arc addresses" ); + + assert!(false); } From 0dee63e7c423f83027918208c48019c659189399 Mon Sep 17 00:00:00 2001 From: nichmor Date: Fri, 12 Sep 2025 15:28:25 +0300 Subject: [PATCH 10/13] misc: fail only on windows --- crates/pixi_command_dispatcher/tests/integration/main.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/crates/pixi_command_dispatcher/tests/integration/main.rs b/crates/pixi_command_dispatcher/tests/integration/main.rs index 2357a9994f..ecf197ea07 100644 --- a/crates/pixi_command_dispatcher/tests/integration/main.rs +++ b/crates/pixi_command_dispatcher/tests/integration/main.rs @@ -620,5 +620,6 @@ async fn source_build_cache_status_clear_works() { "expected different Arc addresses" ); - assert!(false); + #[cfg(windows)] + unreachable!("Expected same Arc on windows"); } From 0e08d9e93b231fc834c56c550f9f8e6992f74171 Mon Sep 17 00:00:00 2001 From: nichmor Date: Fri, 12 Sep 2025 16:36:03 +0300 Subject: [PATCH 11/13] misc: test weak references --- .../tests/integration/main.rs | 43 +++++++++++++++---- 1 file changed, 35 insertions(+), 8 deletions(-) diff --git a/crates/pixi_command_dispatcher/tests/integration/main.rs b/crates/pixi_command_dispatcher/tests/integration/main.rs index ecf197ea07..a174aa9378 100644 --- a/crates/pixi_command_dispatcher/tests/integration/main.rs +++ b/crates/pixi_command_dispatcher/tests/integration/main.rs @@ -577,14 +577,28 @@ async fn source_build_cache_status_clear_works() { .source_build_cache_status(spec.clone()) .await .expect("query succeeds"); + + // let initial_strong_count = std::sync::Arc::strong_count(&first); + + // Create a weak reference to track the original + let weak_first = std::sync::Arc::downgrade(&first); + let second = dispatcher .source_build_cache_status(spec.clone()) .await .expect("query succeeds"); + // let second_strong_count = std::sync::Arc::strong_count(&second); + // Cached result should return the same Arc assert!(std::sync::Arc::ptr_eq(&first, &second)); + // assert_eq!( + // initial_strong_count + 1, + // second_strong_count, + // "expected strong count to increase by one" + // ); + // assert!(ptr::eq(&first, &second)); // save address so we can compare them later @@ -611,15 +625,28 @@ async fn source_build_cache_status_clear_works() { .await .expect("query succeeds"); - let third_address = format!("{:p}", third); + // Check if the original Arc is truly gone + assert!( + weak_first.upgrade().is_none(), + "Original Arc should be deallocated after cache clear" + ); + + // let third_strong_count = std::sync::Arc::strong_count(&third); - eprintln!("third address: {third_address}"); + // assert_eq!( + // third_strong_count, 1, + // "expected strong count to be one for a fresh Arc" + // ); - assert_ne!( - first_address, third_address, - "expected different Arc addresses" - ); + // let third_address = format!("{:p}", third); - #[cfg(windows)] - unreachable!("Expected same Arc on windows"); + // eprintln!("third address: {third_address}"); + + // assert_ne!( + // first_address, third_address, + // "expected different Arc addresses" + // ); + + // #[cfg(windows)] + // unreachable!("Expected same Arc on windows"); } From 11f3453d52820441c1ed9c0cc27ca8c13553bd93 Mon Sep 17 00:00:00 2001 From: nichmor Date: Fri, 12 Sep 2025 16:36:16 +0300 Subject: [PATCH 12/13] misc: test weak references --- crates/pixi_command_dispatcher/tests/integration/main.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/pixi_command_dispatcher/tests/integration/main.rs b/crates/pixi_command_dispatcher/tests/integration/main.rs index a174aa9378..0d90829830 100644 --- a/crates/pixi_command_dispatcher/tests/integration/main.rs +++ b/crates/pixi_command_dispatcher/tests/integration/main.rs @@ -620,7 +620,7 @@ async fn source_build_cache_status_clear_works() { // Clear and expect a fresh Arc on next query dispatcher.clear_filesystem_caches().await; - let third = dispatcher + let _third = dispatcher .source_build_cache_status(spec) .await .expect("query succeeds"); From 683d47f1e82b401407c58a8215aa8680155741d3 Mon Sep 17 00:00:00 2001 From: nichmor Date: Fri, 12 Sep 2025 16:58:33 +0300 Subject: [PATCH 13/13] misc: use weakref to keep track of arcs --- .../tests/integration/main.rs | 46 ++----------------- 1 file changed, 3 insertions(+), 43 deletions(-) diff --git a/crates/pixi_command_dispatcher/tests/integration/main.rs b/crates/pixi_command_dispatcher/tests/integration/main.rs index 0d90829830..b24992b92d 100644 --- a/crates/pixi_command_dispatcher/tests/integration/main.rs +++ b/crates/pixi_command_dispatcher/tests/integration/main.rs @@ -578,9 +578,8 @@ async fn source_build_cache_status_clear_works() { .await .expect("query succeeds"); - // let initial_strong_count = std::sync::Arc::strong_count(&first); - - // Create a weak reference to track the original + // Create a weak reference to track that the original Arc is dropped + // after clearing the cache let weak_first = std::sync::Arc::downgrade(&first); let second = dispatcher @@ -588,35 +587,14 @@ async fn source_build_cache_status_clear_works() { .await .expect("query succeeds"); - // let second_strong_count = std::sync::Arc::strong_count(&second); - // Cached result should return the same Arc assert!(std::sync::Arc::ptr_eq(&first, &second)); - // assert_eq!( - // initial_strong_count + 1, - // second_strong_count, - // "expected strong count to increase by one" - // ); - - // assert!(ptr::eq(&first, &second)); - - // save address so we can compare them later - let first_address = format!("{:p}", first); - let second_address = format!("{:p}", second); - - eprintln!("first address: {first_address}"); - eprintln!("second address: {second_address}"); - // now drop the cached entries to release the Arc // which will unlock the fd locks that we hold on the cache files drop(first); drop(second); - // #[cfg(windows)] - // // testing the theory of "drop releases the lock" is hard on windows - // tokio::time::sleep(tokio::time::Duration::from_secs(3)).await; - // Clear and expect a fresh Arc on next query dispatcher.clear_filesystem_caches().await; @@ -626,27 +604,9 @@ async fn source_build_cache_status_clear_works() { .expect("query succeeds"); // Check if the original Arc is truly gone + // and we have a fresh one assert!( weak_first.upgrade().is_none(), "Original Arc should be deallocated after cache clear" ); - - // let third_strong_count = std::sync::Arc::strong_count(&third); - - // assert_eq!( - // third_strong_count, 1, - // "expected strong count to be one for a fresh Arc" - // ); - - // let third_address = format!("{:p}", third); - - // eprintln!("third address: {third_address}"); - - // assert_ne!( - // first_address, third_address, - // "expected different Arc addresses" - // ); - - // #[cfg(windows)] - // unreachable!("Expected same Arc on windows"); }