From 392961ed0dd431b1d66403e16d1ccc6a5a5f5aa9 Mon Sep 17 00:00:00 2001 From: Ben Kunkle Date: Fri, 8 May 2026 10:32:59 -0500 Subject: [PATCH] Fix flaky terminal kill task test (#56194) Failed CI run: https://github.com/zed-industries/zed/actions/runs/25559568951/job/75027378760?pr=56181 test_kill_active_task_on_completed_task_is_noop was flaking on Linux. It's sibling was just waiting 200ms for PTY events to be handled by alacritty. This PR polls the PTY instead of waiting an arbitrary amount of time Release Notes: - N/A --- crates/terminal/src/terminal.rs | 28 ++++++++++++++++++++++++---- 1 file changed, 24 insertions(+), 4 deletions(-) diff --git a/crates/terminal/src/terminal.rs b/crates/terminal/src/terminal.rs index 99b3b9d6ce4ad2656247d34f8da81047c6b5704c..7069110edd30e304f37c2b9263d69a4750f4dec9 100644 --- a/crates/terminal/src/terminal.rs +++ b/crates/terminal/src/terminal.rs @@ -3341,6 +3341,27 @@ mod tests { }); } + /// Polls the terminal content until `expected` appears, or panics after ~1s. + /// The PTY IO thread writes into the terminal grid independently of the + /// GPUI executor, so we need a real-time polling loop to synchronize. + async fn assert_content_eventually( + terminal: &Entity, + expected: &str, + cx: &mut TestAppContext, + ) { + let mut content = String::new(); + for _ in 0..100 { + content = terminal.update(cx, |term, _| term.get_content()); + if content.contains(expected) { + return; + } + cx.background_executor + .timer(Duration::from_millis(10)) + .await; + } + panic!("Expected terminal content to contain {expected:?}, got: {content}"); + } + /// Test that kill_active_task properly terminates both the foreground process /// and the shell, allowing wait_for_completed_task to complete and output to be captured. #[cfg(unix)] @@ -3353,10 +3374,7 @@ mod tests { let (terminal, completion_rx) = build_test_terminal(cx, "echo", &["test_output_before_kill; sleep 60"]).await; - // Wait a bit for the echo to execute and produce output - cx.background_executor - .timer(Duration::from_millis(200)) - .await; + assert_content_eventually(&terminal, "test_output_before_kill", cx).await; // Kill the active task terminal.update(cx, |term, _cx| { @@ -3400,6 +3418,8 @@ mod tests { .expect("Should receive exit status"); assert_eq!(exit_status, Some(ExitStatus::default())); + assert_content_eventually(&terminal, "done", cx).await; + // Now try to kill - should be a no-op since task already completed terminal.update(cx, |term, _cx| { term.kill_active_task();