Files
tty7/.github/workflows
l0ng-aiandl0ng-ai 4f37fa8eb8 fix(transport): bound the Windows test hang — no unbounded loopback accept, and CI timeouts (#261)
* ci: bound the Windows test hang and stop superseded runs holding slots

The Windows `Test` step intermittently hangs — roughly one run in ten, on
any branch, while the same commit passes on a re-run. `cargo test` has no
timeout of its own, so every occurrence ran to GitHub's six-hour job limit:
three times in one day a 75-second step held a runner slot for hours and
reported nothing about which test was stuck. One of them took the runner
down with it ("the hosted runner lost communication with the server"), and
while those zombies held slots an unrelated PR's macOS job queued for two
and a half hours.

Three changes, none of which fix the hang itself:

- `timeout-minutes` on the `Test` step (20) and `Build` step (30), plus a
  60-minute job backstop. The honest budget is ~75s warm and ~3.5 min when
  the step also compiles the test targets, so a trip means a hang.
- A Windows-only post-mortem step on failure that dumps the process table.
  libtest names a test when it *finishes*, so the hung one is the name
  missing from a truncated list; the surviving test binary names its crate
  and test target instead.
- `concurrency` with `cancel-in-progress` for pull requests, so a
  superseded run stops competing for the shared concurrent-job budget.
  Pushes to main are exempt: each commit's run is the record of whether
  that commit was green.

The hang's cause is still unknown and cannot be reproduced off a Windows
runner. This makes it report in 20 minutes instead of costing six hours.

* fix(transport): no Windows test may block forever on a loopback accept

The three `cfg(windows)` tests in the transport's test module held five
unbounded `listener.accept().unwrap()` calls, each paired with a client
thread that `unwrap()`s its `connect`. When such a thread panics — a
transient loopback refusal on a loaded runner is enough — nothing is left
to wake the accept, and nothing is left to feed the handshake read after
it. The test does not fail; the whole test binary stops.

That is the shape of the hang CI has been paying for: Windows-only (these
tests are `cfg(windows)`, so no developer's macOS run executes them),
intermittent, and mute — libtest names a test only once it *finishes*, so
no log ever said which one was stuck.

`accept_within` polls a non-blocking listener against a ten-second
deadline, then restores blocking mode and puts a read timeout on the
accepted socket. Winsock hands an accepted socket the listener's blocking
mode, so clearing it on the returned stream is a real step, not a no-op.
Verified on the host target, where the logic is identical std code: a real
client is still accepted and its handshake read still works, and a client
that never arrives fails in 10.0s instead of never.

Whether this is the exact hang CI hit is unproven — it cannot be
reproduced off a Windows runner, and `aws-lc-sys` will not even build for
the Windows target on a mac. It is the only Windows-only cluster of
unbounded network waits in the tree, and it matches every observed
symptom. Either way the six-hour failure mode is gone from here.

---------

Co-authored-by: l0ng-ai <24760907+l0ng-ai@users.noreply.github.com>
2026-07-30 16:23:59 +08:00
..