test(win): full UI-mode hang repro harness for #798 follow-up#877
Conversation
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>
|
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. |
|
Thanks @Flipper1994 — the harness itself is excellent. I reviewed it adversarially and it's security-clean, the guards are genuine (the deterministic Our public repos have a strict policy: no Claude/Anthropic/AI attribution in commit messages. This commit carries: Since we merge with a merge commit (no squash), those would land on Could you |
|
Update: merged as-is ( For future cbm PRs, please drop the |
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:Test-only — no production code changes. Three guards, all in the existing
security/httpdsuites (run on the currenttest-windowsCI 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 inheritableAFD/listening socket — the exact handle class that deadlocked git in #798 — then spawns
the test binary through
cbm_popen(acmd.exegrandchild, i.e. git's real spawn shape)in a new
__cbm_sockprobere-exec mode (tests/test_main.c). The child reports via exitcode whether that socket handle is live in its address space:
cmd.exeinherits only{pipe, NUL}→ socket absent →getsockoptfails → child exit0→ GREEN_popenregression:bInheritHandles=TRUEleaks the socket transitively throughcmd.exe→getsockoptsucceeds → child exit42→ REDUnlike the existing git-version round-trip, this is deterministic on any Windows and
does not depend on the MSYS2 git build reproducing the
NtQueryObjecthang.Guard 2 — end-to-end liveness under live UI sockets (
tests/test_httpd.c)ui_server_list_projects_responds_under_watchdog:POST /rpc list_projectsto therunning single-threaded UI server (holding live listening sockets) with a client
SO_RCVTIMEOwatchdog. 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 livelistening/AFD handles in-process, run
cbm_git_context_resolve— the exact pathlist_projectsruns (add_git_context_json → resolve → cbm_popen(git)) — on a workerthread under a
WaitForSingleObject(30s)watchdog. A hang → FAIL. SKIPs where gitcannot init a repo via
system()(matching the existingtest_git_context.cpattern).Local verification (MSYS2/MinGW, native Windows)
popen_isolates_listening_socketrc == 42, socket leaked)ui_server_list_projects_responds_under_watchdoggit_context_resolve_no_hang_under_live_ui_socketssecurity: 41 passed.httpd: 42 passed. Compiles clean under-Werror.Design note: the
NtQueryObjectdeadlock is environment-sensitive (not every git-for-Windowsbuild 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