@@ -11,6 +11,7 @@ mod common;
1111
1212use common:: { init, OptimizationLevel , FIXTURES } ;
1313use lazy_static:: lazy_static;
14+ use std:: collections:: HashMap ;
1415use std:: ffi:: OsString ;
1516use std:: io:: Write ;
1617use std:: process:: Stdio ;
@@ -24,8 +25,9 @@ use tokio::time::timeout;
2425
2526// Global test program management
2627lazy_static ! {
27- static ref GLOBAL_TEST_MANAGER : Arc <RwLock <Option <GlobalTestProcess >>> =
28- Arc :: new( RwLock :: new( None ) ) ;
28+ // Maintain one process per optimization level to avoid cross-test interference.
29+ static ref GLOBAL_TEST_MANAGER : Arc <RwLock <HashMap <OptimizationLevel , GlobalTestProcess >>> =
30+ Arc :: new( RwLock :: new( HashMap :: new( ) ) ) ;
2931}
3032
3133struct GlobalTestProcess {
@@ -111,58 +113,47 @@ impl GlobalTestProcess {
111113async fn get_global_test_pid_with_opt ( opt_level : OptimizationLevel ) -> anyhow:: Result < u32 > {
112114 let manager = GLOBAL_TEST_MANAGER . clone ( ) ;
113115
114- // Read lock first to check if process exists and matches optimization level
116+ // Fast path: check if we already have a live process for this opt level
115117 {
116118 let read_guard = manager. read ( ) . await ;
117- if let Some ( process) = & * read_guard {
118- // Check if optimization level matches and process is still running
119- if process. optimization_level == opt_level {
120- let status = std:: process:: Command :: new ( "kill" )
121- . args ( & [ "-0" , & process. pid . to_string ( ) ] )
122- . status ( ) ;
123-
124- if status. map ( |s| s. success ( ) ) . unwrap_or ( false ) {
125- return Ok ( process. pid ) ;
126- }
127- }
128- // Either wrong opt level or process is dead, we'll need to start a new one
129- }
130- }
131-
132- // Write lock to start new process
133- let mut write_guard = manager. write ( ) . await ;
134-
135- // Double-check in case another thread started it
136- if let Some ( process) = & * write_guard {
137- if process. optimization_level == opt_level {
119+ if let Some ( process) = read_guard. get ( & opt_level) {
138120 let status = std:: process:: Command :: new ( "kill" )
139121 . args ( & [ "-0" , & process. pid . to_string ( ) ] )
140122 . status ( ) ;
141-
142123 if status. map ( |s| s. success ( ) ) . unwrap_or ( false ) {
143124 return Ok ( process. pid ) ;
144125 }
145126 }
146127 }
147128
148- // Terminate existing process if it has different optimization level
149- if let Some ( old_process) = write_guard. take ( ) {
150- if old_process. optimization_level != opt_level {
151- println ! (
152- "🔄 Switching from {} to {}, terminating old process" ,
153- old_process. optimization_level. description( ) ,
154- opt_level. description( )
155- ) ;
156- let _ = old_process. terminate ( ) . await ;
129+ // Slow path: create or replace the entry for this opt level
130+ let mut write_guard = manager. write ( ) . await ;
131+
132+ // Double-check under write lock in case another task started it
133+ if let Some ( process) = write_guard. get ( & opt_level) {
134+ let status = std:: process:: Command :: new ( "kill" )
135+ . args ( & [ "-0" , & process. pid . to_string ( ) ] )
136+ . status ( ) ;
137+ if status. map ( |s| s. success ( ) ) . unwrap_or ( false ) {
138+ return Ok ( process. pid ) ;
157139 }
158140 }
159141
142+ // If an old process exists for this opt level, remove it first (drop lock before awaiting)
143+ let old_proc = write_guard. remove ( & opt_level) ;
144+ drop ( write_guard) ;
145+
146+ if let Some ( old) = old_proc {
147+ let _ = old. terminate ( ) . await ;
148+ }
149+
160150 // Start new process with the requested optimization level
161151 let new_process = GlobalTestProcess :: start_with_opt ( opt_level) . await ?;
162152 let pid = new_process. get_pid ( ) ;
163153
164- * write_guard = Some ( new_process) ;
165-
154+ // Re-acquire write lock to insert the new process
155+ let mut write_guard = manager. write ( ) . await ;
156+ write_guard. insert ( opt_level, new_process) ;
166157 Ok ( pid)
167158}
168159
@@ -172,8 +163,12 @@ pub async fn cleanup_global_test_process() -> anyhow::Result<()> {
172163 let manager = GLOBAL_TEST_MANAGER . clone ( ) ;
173164 let mut write_guard = manager. write ( ) . await ;
174165
175- if let Some ( process) = write_guard. take ( ) {
176- process. terminate ( ) . await ?;
166+ // Terminate all managed processes (for every optimization level)
167+ let processes: Vec < GlobalTestProcess > = write_guard. drain ( ) . map ( |( _, p) | p) . collect ( ) ;
168+ drop ( write_guard) ;
169+
170+ for proc in processes. into_iter ( ) {
171+ let _ = proc. terminate ( ) . await ;
177172 }
178173
179174 Ok ( ( ) )
@@ -259,7 +254,6 @@ async fn run_ghostscope_with_script_opt(
259254 OsString :: from( "--no-save-llvm-ir" ) ,
260255 OsString :: from( "--no-save-ebpf" ) ,
261256 OsString :: from( "--no-save-ast" ) ,
262- OsString :: from( "--no-log" ) ,
263257 ] ;
264258 let command_display = format ! (
265259 "{} {}" ,
0 commit comments