//! Regression: request_stop racing an alloc-under-lock must not poison any //! runtime mutex. Before the fix, check_cancelled() fired regardless of //! PREEMPTION_ENABLED, so a sentinel unwind could trigger inside with_shared //! (which allocates: run_queue.push_back, waiters.push, etc), poisoning the //! shared mutex and cascading lock().unwrap() panics. use smarm::runtime::{init, Config}; use std::sync::atomic::{AtomicUsize, Ordering}; use std::sync::Arc; #[test] fn stop_storm_does_not_poison_runtime() { let rt = init(Config::exact(4)); let completed = Arc::new(AtomicUsize::new(0)); let c = completed.clone(); rt.run(move || { // Spawn many short actors that allocate + yield heavily (hammering // with_shared), and request_stop each one mid-flight from siblings. let mut handles = Vec::new(); for _ in 0..200 { let h = smarm::spawn(|| { for _ in 0..50 { let _v: Vec = Vec::with_capacity(64); // alloc → maybe_preempt smarm::yield_now(); } }); handles.push(h); } // Cancel half of them; the others run to completion. If any lock got // poisoned the runtime would panic on a subsequent lock().unwrap(). for (i, h) in handles.iter().enumerate() { if i % 2 == 0 { smarm::request_stop(h.pid()); } } for h in handles { let _ = h.join(); } c.fetch_add(1, Ordering::SeqCst); }); assert_eq!(completed.load(Ordering::SeqCst), 1, "root completed cleanly"); }