From f3fcbc7784ec2bda4e83603f263d67ea0ca84078 Mon Sep 17 00:00:00 2001 From: CodeWhale Bot Date: Wed, 23 Sep 2026 10:02:22 -0700 Subject: [PATCH] test(runtime-api): wait for the old owner lock before a restart proof turn_operation_lookup_is_authenticated_read_only_and_survives_restart failed on Ubuntu CI (#6438 run 35886856223, job 107269234021) with "Mock Runtime execution scope is already owned" and passed 3/3 locally. The old test server tears its runtime down on its own thread after the abort, so its mock TaskManager can still hold the execution-scope owner lock after the RuntimeThreadManager the test waits on has dropped. Refusing a second owner is correct product behavior; the restart now retries only on that refusal, within the existing CI-scaled 10 s deadline, and any other startup error still fails immediately. Evidence: the test passes locally (1 passed, 0 failed); hosted load is the acceptance. TUI all-target/all-feature Clippy with CI flags passed. Co-Authored-By: Claude Opus 5.5 (1M context) --- crates/tui/src/runtime_api/tests.rs | 35 +++++++++++++++++++++-------- 1 file changed, 26 insertions(+), 9 deletions(-) diff --git a/crates/tui/src/runtime_api/tests.rs b/crates/tui/src/runtime_api/tests.rs index 85e61e6a54..801a20acb7 100644 --- a/crates/tui/src/runtime_api/tests.rs +++ b/crates/tui/src/runtime_api/tests.rs @@ -4176,15 +4176,32 @@ async fn turn_operation_lookup_is_authenticated_read_only_and_survives_restart() .await .context("old Runtime did not release its store before restart")?; - let (addr, _manager, server) = spawn_test_server_with_root_token_mobile_workspace( - root, - sessions, - Some(token.into()), - false, - workspace, - ) - .await? - .context("loopback listener required for restarted lookup proof")?; + // The old server tears its runtime down on its own thread after the + // abort, so its mock TaskManager can hold the execution-scope owner lock + // a moment longer than the thread manager above. A second owner is + // correctly refused; wait for the release instead of racing it. + let deadline = tokio::time::Instant::now() + ci_scaled(Duration::from_secs(10)); + let (addr, _manager, server) = loop { + match spawn_test_server_with_root_token_mobile_workspace( + root.clone(), + sessions.clone(), + Some(token.into()), + false, + workspace.clone(), + ) + .await + { + Err(error) + if format!("{error:#}").contains("execution scope is already owned") + && tokio::time::Instant::now() < deadline => + { + sleep(Duration::from_millis(20)).await; + } + started => { + break started?.context("loopback listener required for restarted lookup proof")?; + } + } + }; // Startup recovery is complete. No Engine is installed in this Runtime. let before = file_bytes(&store_root)?; let response = client