diff options
| author | Ogulcan Celik <ogulcancelik@gmail.com> | 2026-07-14 23:40:12 +0300 |
|---|---|---|
| committer | Ogulcan Celik <ogulcancelik@gmail.com> | 2026-07-14 23:40:35 +0300 |
| commit | 80d2958abad152f515aa356e8190e89a80485342 (patch) | |
| tree | ce731f033f51dd17bb6f8084914576b0f7c73bc7 /src/detect | |
| parent | 464c658fdd3a9257b1eb5095b0ae024a306b29ee (diff) | |
fix(linux): scope foreground process discovery to panes
refs #1399
Diffstat (limited to 'src/detect')
| -rw-r--r-- | src/detect/mod.rs | 72 |
1 files changed, 54 insertions, 18 deletions
diff --git a/src/detect/mod.rs b/src/detect/mod.rs index bc7569e3..5c220b52 100644 --- a/src/detect/mod.rs +++ b/src/detect/mod.rs @@ -1098,19 +1098,23 @@ mod tests { // ---- Process identification (real PTY) ---- #[cfg(target_os = "linux")] - #[test] - fn foreground_job_detects_sleep() { - use portable_pty::{native_pty_system, CommandBuilder, PtySize}; - - let pty_system = native_pty_system(); - let pair = pty_system - .openpty(PtySize { + fn open_test_pty() -> portable_pty::PtyPair { + portable_pty::native_pty_system() + .openpty(portable_pty::PtySize { rows: 24, cols: 80, pixel_width: 0, pixel_height: 0, }) - .expect("failed to open pty"); + .expect("failed to open pty") + } + + #[cfg(target_os = "linux")] + #[test] + fn foreground_job_detects_sleep() { + use portable_pty::CommandBuilder; + + let pair = open_test_pty(); // Spawn "sleep 999" — a known, deterministic process let mut cmd = CommandBuilder::new("sleep"); @@ -1140,18 +1144,10 @@ mod tests { #[cfg(target_os = "linux")] #[test] fn foreground_job_detects_shell_running_command() { - use portable_pty::{native_pty_system, CommandBuilder, PtySize}; + use portable_pty::CommandBuilder; use std::io::Write; - let pty_system = native_pty_system(); - let pair = pty_system - .openpty(PtySize { - rows: 24, - cols: 80, - pixel_width: 0, - pixel_height: 0, - }) - .expect("failed to open pty"); + let pair = open_test_pty(); // Spawn a shell, then run a command inside it let cmd = CommandBuilder::new("sh"); @@ -1183,6 +1179,46 @@ mod tests { #[cfg(target_os = "linux")] #[test] + fn foreground_job_detects_agent_behind_shell_wrapper() { + use portable_pty::CommandBuilder; + + let pair = open_test_pty(); + + let mut cmd = CommandBuilder::new("bash"); + cmd.arg("-c"); + cmd.arg("bash -c 'exec -a codex sleep 999' & wait"); + let mut child = pair.slave.spawn_command(cmd).expect("failed to spawn"); + let pid = child.process_id().expect("no pid"); + std::thread::sleep(std::time::Duration::from_millis(100)); + + let job = foreground_job(pid); + let process_group_id = job.as_ref().map(|job| job.process_group_id).unwrap_or(pid); + unsafe { + libc::kill(-(process_group_id as i32), libc::SIGKILL); + } + child.wait().ok(); + + let job = job.expect("expected foreground job"); + assert!( + job.processes.iter().any(|process| process.name == "bash") + && job.processes.iter().any(|process| { + process.name == "sleep" + && process + .argv + .as_deref() + .and_then(|argv| argv.first()) + .is_some_and(|argv0| argv0 == "codex") + }), + "expected wrapper and agent child in {job:?}" + ); + assert_eq!( + identify_agent_in_job(&job), + Some((Agent::Codex, "codex".to_string())) + ); + } + + #[cfg(target_os = "linux")] + #[test] fn proc_stat_parsing_handles_spaces_in_comm() { // Verify our /proc/pid/stat parser correctly extracts fields // even when (comm) could contain spaces. |
