ci(soak): abrupt-death ConPTY orphan probe (the failure-mode the clean soak misses)

The clean-path soak found no leak on windows-latest — because orderly close()
reaps every host. That never exercises the freeze hypothesis (T-424), which is
the parent dying WITHOUT teardown while a child is live.

This probe does. conpty_orphan_probe.dart starts N real WindowsPty sessions on
long-lived children and blocks WITHOUT ever calling close(); soak-conpty-kill.ps1
force-kills only the dart.exe parent (taskkill /F, no /T) once the hosts are up
and counts the conhost/OpenConsole/cmd processes that SURVIVE. Absent a
kill-on-close Job Object, abrupt parent death should orphan them — a survivor
count that climbs across cycles is the leak signature. The same probe will prove
the T-424 fix: with the job, survivors should drop to ~0.

Wired as a second job in windows-soak.yml (workflow_dispatch + when the kit
changes). Diagnostic only, never a gate, always exits 0; publishes the verdict
to the job summary and uploads the CSV. Not part of the regular test suite.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-06-15 08:58:14 +02:00
co-authored by Claude Opus 4.8
parent c1d14bbaf0
commit 2953207960
3 changed files with 266 additions and 1 deletions
+43 -1
View File
@@ -19,8 +19,14 @@ on:
workflow_dispatch:
inputs:
iterations:
description: How many times to run the ConPTY suite
description: How many times to run the ConPTY suite (clean-path soak)
default: "25"
kill_iterations:
description: Spawn+force-kill cycles (abrupt-death orphan probe)
default: "15"
ptys_per_iter:
description: WindowsPty sessions spawned per kill cycle
default: "2"
push:
branches: [windows-support]
paths:
@@ -57,3 +63,39 @@ jobs:
name: conpty-soak
path: soak-out
if-no-files-found: warn
conpty-kill-probe:
# Abrupt-death half: force-kill the parent dart.exe mid-life (no close(),
# no Job Object) and count the ConPTY hosts that survive. This is the path
# the freeze hypothesis (T-424) actually implicates — the clean-path soak
# above never exercises it. Diagnostic only; always succeeds.
runs-on: windows-latest
timeout-minutes: 30
steps:
- uses: actions/checkout@v4
- uses: subosito/flutter-action@v2
with:
channel: stable
- run: flutter --version
- run: flutter pub get
- name: ConPTY abrupt-death orphan probe
shell: pwsh
run: |
$iters = "${{ github.event.inputs.kill_iterations }}"
if (-not $iters) { $iters = "15" }
$ptys = "${{ github.event.inputs.ptys_per_iter }}"
if (-not $ptys) { $ptys = "2" }
tools/windows-verify/soak-conpty-kill.ps1 -Iterations ([int]$iters) -PtysPerIter ([int]$ptys) -OutDir "$env:GITHUB_WORKSPACE/kill-out"
- name: Publish verdict to job summary
if: always()
shell: pwsh
run: |
$s = Get-ChildItem "$env:GITHUB_WORKSPACE/kill-out/*.summary.txt" -ErrorAction SilentlyContinue | Select-Object -First 1
if ($s) { Get-Content $s.FullName | Add-Content $env:GITHUB_STEP_SUMMARY }
- name: Upload kill-probe CSV + summary
if: always()
uses: actions/upload-artifact@v4
with:
name: conpty-kill-probe
path: kill-out
if-no-files-found: warn