From 02a6cb24ce5526b2e93a43a2d086da0e82ced509 Mon Sep 17 00:00:00 2001 From: jars Date: Sat, 9 May 2026 11:42:03 +0100 Subject: [PATCH] fix(core): serialise tuning env-var tests behind a lock Without a lock, env_var_bypasses_clamps (set_var + remove_var) and matches_existing_clamp_when_no_clamps_apply (remove_var) race under cargo's parallel test runner. Task 2.2 will add another remove_var call, compounding the race. Adds a #[cfg(test)] static THREAD_ENV_LOCK and a closure-style with_thread_env_lock helper, mirroring power::with_override. Co-Authored-By: Claude Sonnet 4.6 --- crates/core/src/tuning.rs | 30 ++++++++++++++++++++++-------- 1 file changed, 22 insertions(+), 8 deletions(-) diff --git a/crates/core/src/tuning.rs b/crates/core/src/tuning.rs index dd2b742..70ec908 100644 --- a/crates/core/src/tuning.rs +++ b/crates/core/src/tuning.rs @@ -63,24 +63,38 @@ pub fn inference_thread_count(_workload: Workload, _gpu_offloaded: bool) -> usiz mod tests { use super::*; + /// Serialises tests that read/write `MAGNOTIA_INFERENCE_THREADS` so + /// they don't race under cargo's parallel test runner. + /// Mirrors the pattern used by `power::with_override`. + fn with_thread_env_lock(body: impl FnOnce() -> R) -> R { + use std::sync::Mutex; + static THREAD_ENV_LOCK: Mutex<()> = Mutex::new(()); + let _lock = THREAD_ENV_LOCK.lock().expect("tuning thread-env lock poisoned"); + body() + } + #[test] fn matches_existing_clamp_when_no_clamps_apply() { // With no env override, no battery, no gpu_offload, helper // should return physical-core count clamped to [2, 8]. // We can't pin physical exactly without mocking num_cpus; just // assert the result is in range. - std::env::remove_var("MAGNOTIA_INFERENCE_THREADS"); - let n = inference_thread_count(Workload::Llm, false); - assert!(n >= MIN_INFERENCE_THREADS && n <= MAX_INFERENCE_THREADS, - "got {n}, expected within [{MIN_INFERENCE_THREADS}, {MAX_INFERENCE_THREADS}]"); + with_thread_env_lock(|| { + std::env::remove_var("MAGNOTIA_INFERENCE_THREADS"); + let n = inference_thread_count(Workload::Llm, false); + assert!(n >= MIN_INFERENCE_THREADS && n <= MAX_INFERENCE_THREADS, + "got {n}, expected within [{MIN_INFERENCE_THREADS}, {MAX_INFERENCE_THREADS}]"); + }); } #[test] fn env_var_bypasses_clamps() { - std::env::set_var("MAGNOTIA_INFERENCE_THREADS", "10"); - let n = inference_thread_count(Workload::Llm, true); - assert_eq!(n, 10); - std::env::remove_var("MAGNOTIA_INFERENCE_THREADS"); + with_thread_env_lock(|| { + std::env::set_var("MAGNOTIA_INFERENCE_THREADS", "10"); + let n = inference_thread_count(Workload::Llm, true); + assert_eq!(n, 10); + std::env::remove_var("MAGNOTIA_INFERENCE_THREADS"); + }); } #[test]