Skip to content

[Bug]: native-runtime 验收把命令写进了还没启动完的 shell — 5 秒轮询预算被 shell 启动吃掉 #33

Closed

Description

@modacker

What breaks

The native-terminal acceptance fails in the test body on the Windows runner:

packages/webui/test/browser/native-runtime.spec.mjs
expect.poll(async () => (await rpc(page, "listTerminals"))[0].output).toContain("WEBUI_NATIVE_ALIVE")
-> Timeout 5000ms exceeded while waiting on the predicate

The teardown's second complaint ("exited" received 1 instead of 6) is a consequence:
the body failed first, so only one terminal was ever created.

Why it happens

The command is written into a shell that has not finished starting up.

The failing run's Playwright trace (artifact webui-browser-windows-latest-1, trace.zip,
which carries the raw return of every listTerminals call) gives the timeline,
with T0 = the moment writeTerminal wrote the command:

moment what the terminal buffer held
T0 + 0 ms the write went into the PTY
T0 + 3957 ms the PowerShell prompt (PS C:\...\workspace> ) appeared
T0 + 4983 ms the typed command was echoed by PSReadLine
T0 + 4991 ms expect.poll threw Timeout 5000ms exceeded

The shell's own start-up took about four of the five seconds the wait was given.
At the moment the wait gave up, the buffer held the echoed command and no output
line
-- the command had not been executed yet, so this is not "the echo was late".

The command itself is written to make a false positive impossible
(Write-Output ('WEBUI_NATIVE_' + 'ALIVE')), so the literal string can only appear
in a real output line. That part of the test is sound.

How often

  • The fork's 152 CI runs contain 10 failed native-runtime jobs. Their forms:
    1 x this one (the body's five-second wait), 1 x the teardown stall (see [Bug]: the native acceptance teardown still times out on Windows — the host stalls inside the service close #30),
    7 x "the native host never started", 1 x "the beforeAll hook timed out".
  • This form was seen exactly once: run 42966373896, Windows attempt 1,
    job 130344433067. The same job's second attempt passed, and the branch's later run
    (42971475734) passed on Windows on the first attempt.
  • On the base commit there was only one native-runtime opportunity and it passed.
    The honest wording is therefore "not observed on base", not "impossible on base".

What this is not

Direction of a fix

Wait until the shell is actually up before writing into it, so the five seconds are
spent on the echo rather than on the shell's start-up. The wait for readiness needs its
own bounded budget and has to fail with a readable message saying how far the terminal
got. Nothing is to be relaxed: the five-second budget for the echo stays five seconds,
no retry is added, no case is skipped, and the expected string does not change.

The same test runs on macOS and Linux, where the shell starts quickly; the readiness
gate must not disturb them.

Activity

  1. modacker commented on Nov 11, 2026

    @modacker
    CollaboratorAuthor

    Fixed in #35 (merge commit defc233).

    The case now waits for the shell before it types anything, with two signals in order: whether the shell has printed anything at all (no prompt text, so the same wait works for PowerShell and for sh), and then a probe the shell executes. The probe is what decides, because "the shell has started" is not yet "the shell is reading" — the prompt arrived about a second before PowerShell began reading. The probe's marker is split the way the command's own marker is split, so the shell's echo of the probe cannot pass for an answer; only its execution can.

    Nothing was loosened: the assertion is unchanged and still gets the same five seconds for the echo. The new budget is a precondition on the write, spent on the shell's start-up.

    CI run 42992507142 on the merged revision: ubuntu-latest, windows-latest and macos-latest all green. The Windows runner — where this failure appeared — passed with the win32 probe.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions