Skip to content

test(win): full UI-mode hang repro harness for #798 follow-up#877

Merged
DeusData merged 1 commit into
DeusData:mainfrom
Flipper1994:fix/798-full-ui-repro-harness
Jul 5, 2026
Merged

test(win): full UI-mode hang repro harness for #798 follow-up#877
DeusData merged 1 commit into
DeusData:mainfrom
Flipper1994:fix/798-full-ui-repro-harness

Conversation

@Flipper1994

Copy link
Copy Markdown
Contributor

test(win): full UI-mode hang repro harness for #798 follow-up

Follow-up to the #798 distill (d2a5975 / #846). Closes the gap Martin flagged in
review, recorded in tests/test_security.c:

NOT proven here: the full UI repro (listening socket + MSYS2 handle walk under a
single-threaded server) — follow-up harness.

Test-only — no production code changes. Three guards, all in the existing
security/httpd suites (run on the current test-windows CI leg, no new build wiring).

Guard 1 — deterministic socket-isolation probe (any Windows, RED-able)

popen_isolates_listening_socket (tests/test_security.c) opens a real inheritable
AFD/listening socket — the exact handle class that deadlocked git in #798 — then spawns
the test binary through cbm_popen (a cmd.exe grandchild, i.e. git's real spawn shape)
in a new __cbm_sockprobe re-exec mode (tests/test_main.c). The child reports via exit
code whether that socket handle is live in its address space:

  • isolated spawn (the fix): cmd.exe inherits only {pipe, NUL} → socket absent →
    getsockopt fails → child exit 0GREEN
  • raw _popen regression: bInheritHandles=TRUE leaks the socket transitively through
    cmd.exegetsockopt succeeds → child exit 42RED

Unlike the existing git-version round-trip, this is deterministic on any Windows and
does not depend on the MSYS2 git build reproducing the NtQueryObject hang.

Guard 2 — end-to-end liveness under live UI sockets (tests/test_httpd.c)

  • ui_server_list_projects_responds_under_watchdog: POST /rpc list_projects to the
    running single-threaded UI server (holding live listening sockets) with a client
    SO_RCVTIMEO watchdog. A wedge → no 200 → hard FAIL, never an infinite CI hang.
  • git_context_resolve_no_hang_under_live_ui_sockets: while the UI server holds live
    listening/AFD handles in-process, run cbm_git_context_resolve — the exact path
    list_projects runs (add_git_context_json → resolve → cbm_popen(git)) — on a worker
    thread under a WaitForSingleObject(30s) watchdog. A hang → FAIL. SKIPs where git
    cannot init a repo via system() (matching the existing test_git_context.c pattern).

Local verification (MSYS2/MinGW, native Windows)

suite with fix with spawn-inherits-all revert
popen_isolates_listening_socket GREEN (exit 0) RED (rc == 42, socket leaked)
ui_server_list_projects_responds_under_watchdog GREEN
git_context_resolve_no_hang_under_live_ui_sockets GREEN

security: 41 passed. httpd: 42 passed. Compiles clean under -Werror.

Design note: the NtQueryObject deadlock is environment-sensitive (not every git-for-Windows
build reproduces it), so Guard 1 is the load-bearing deterministic RED-able guard and
Guard 2 the liveness invariant that catches the hang wherever it reproduces.

🤖 Generated with Claude Code

Closes the gap flagged in the distill review (test_security.c: "NOT proven
here: the full UI repro — listening socket + MSYS2 handle walk under a
single-threaded server"). Test-only; no production code changes.

Guard 1 — deterministic socket-isolation probe (any Windows, RED-able):
  popen_isolates_listening_socket (tests/test_security.c) opens a real
  inheritable AFD/listening socket — the exact handle class that deadlocked
  git in DeusData#798 — then spawns THIS binary through cbm_popen (a cmd.exe
  grandchild, git's spawn shape) in a new __cbm_sockprobe re-exec mode
  (tests/test_main.c). The child reports via exit code whether that socket
  handle is live in its address space: isolated spawn -> getsockopt fails ->
  exit 0 (GREEN); raw-_popen regression leaks it transitively through
  cmd.exe -> getsockopt succeeds -> exit 42 (RED). Verified RED with a local
  spawn-inherits-all revert, GREEN with the isolated spawn.

Guard 2 — end-to-end liveness under live UI sockets (tests/test_httpd.c):
  - ui_server_list_projects_responds_under_watchdog: POST /rpc list_projects
    to the running single-threaded UI server with a client SO_RCVTIMEO
    watchdog; a wedge -> no 200 -> hard FAIL, never an infinite CI hang.
  - git_context_resolve_no_hang_under_live_ui_sockets: while the UI server
    holds live listening/AFD handles in-process, run cbm_git_context_resolve
    (the exact path list_projects takes) on a worker thread under a
    WaitForSingleObject(30s) watchdog; a hang -> FAIL. SKIPs where git cannot
    init a repo via system().

All three run in the existing security/httpd suites on the test-windows CI
leg; no new build wiring.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018g9f9jr5S46BfKaDvDykBp
Signed-off-by: Flipper <jacobphilipp@ymail.com>
@Flipper1994 Flipper1994 requested a review from DeusData as a code owner July 5, 2026 08:25
@DeusData DeusData added bug Something isn't working windows Windows-specific issues stability/performance Server crashes, OOM, hangs, high CPU/memory ux/behavior Display bugs, docs, adoption UX priority/normal Standard review queue; useful PR with ordinary maintainer urgency. labels Jul 5, 2026
@DeusData

DeusData commented Jul 5, 2026

Copy link
Copy Markdown
Owner

Thanks for the focused Windows follow-up. Triage: test coverage for the #798 UI hang class, under #394.

Review will check that the harness is deterministic on Windows CI, remains test-only, and does not introduce a new platform-specific flake. This is a useful guard for the handle-inheritance fix path.

@DeusData

DeusData commented Jul 5, 2026

Copy link
Copy Markdown
Owner

Thanks @Flipper1994 — the harness itself is excellent. I reviewed it adversarially and it's security-clean, the guards are genuine (the deterministic popen_isolates_listening_socket, RED on a raw-_popen revert / GREEN on the isolated spawn, is exactly the load-bearing guard we want), cross-platform-safe (all the Windows code is properly #ifdef _WIN32 / SKIP_PLATFORM-gated — confirmed by the green Linux/macOS legs), and cleanly test-only. Ready to merge on one housekeeping item.

Our public repos have a strict policy: no Claude/Anthropic/AI attribution in commit messages. This commit carries:

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018g9f9jr5S46BfKaDvDykBp

Since we merge with a merge commit (no squash), those would land on main verbatim. Heads-up too: the Claude-Session: line exposes a private claude.ai session URL of yours — worth dropping for your own sake.

Could you git commit --amend to remove those two trailers (keep your Signed-off-by) and force-push the branch? The same applies to cbm PRs going forward. Once that's in I'll re-diff and merge — everything else is green. Really nice work on this one 🙏

@DeusData DeusData merged commit dafec04 into DeusData:main Jul 5, 2026
15 checks passed
@DeusData

DeusData commented Jul 5, 2026

Copy link
Copy Markdown
Owner

Update: merged as-is (dafec04c) — no amend needed, we made a one-time exception here since the harness itself is clean and this is high-priority Windows coverage. Thank you for the excellent work! 🙏

For future cbm PRs, please drop the Co-Authored-By: Claude / Claude-Session trailers from commit messages — it's a public-repo policy — and keep that Claude-Session: URL out of public commits for your own privacy. Appreciate it!

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

Labels

bug Something isn't working priority/normal Standard review queue; useful PR with ordinary maintainer urgency. stability/performance Server crashes, OOM, hangs, high CPU/memory ux/behavior Display bugs, docs, adoption UX windows Windows-specific issues

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants