Skip to content

Commit 156ee63

Browse files
committed
fix: correct sample program global instance for o2 version
1 parent 23543bb commit 156ee63

2 files changed

Lines changed: 34 additions & 40 deletions

File tree

ghostscope/tests/common/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ static COMPILE_OPTIMIZED: Once = Once::new();
6767
static COMPILE_STRIPPED: Once = Once::new();
6868

6969
/// Optimization level for test program compilation
70-
#[derive(Debug, Clone, Copy, PartialEq)]
70+
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
7171
pub enum OptimizationLevel {
7272
Debug, // -O0 (default)
7373
#[allow(dead_code)]

ghostscope/tests/script_execution.rs

Lines changed: 33 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ mod common;
1111

1212
use common::{init, OptimizationLevel, FIXTURES};
1313
use lazy_static::lazy_static;
14+
use std::collections::HashMap;
1415
use std::ffi::OsString;
1516
use std::io::Write;
1617
use std::process::Stdio;
@@ -24,8 +25,9 @@ use tokio::time::timeout;
2425

2526
// Global test program management
2627
lazy_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

3133
struct GlobalTestProcess {
@@ -111,58 +113,47 @@ impl GlobalTestProcess {
111113
async 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

Comments
 (0)