Repository navigation
Description
Windows: web UI hangs forever — list_projects deadlocks the HTTP server (git subprocess via _popen)
Summary
On Windows, with the graph UI enabled (--ui=true), the web UI never loads: the
page shell is served but the app stays blank. The cause is that the MCP tool
list_projects hangs forever and, because the UI HTTP server is
single-threaded, wedges the entire server — no further request is answered.
- Affected: Windows, UI mode only (
--ui=true/ the web graph). Reproduced
with the production binary built frommain(cbm-with-ui). - Not affected: the plain MCP-stdio server (no UI) and the CLI —
list_projects
returns instantly there. That is why normal MCP usage never showed the problem. - Requires: git-for-Windows (the MSYS2/Cygwin build) on
PATH, which is the
standard Windows git.
Root cause (confirmed with a debugger)
list_projects resolves git context per project:
add_git_context_json → cbm_git_context_resolve → git_capture → cbm_popen
(src/git/git_context.c). On Windows cbm_popen is the CRT _popen, which spawns
the child with CreateProcess(bInheritHandles = TRUE) and therefore leaks every
inheritable handle the server holds into the git child — including the
Winsock/AFD helper handles that only exist once the HTTP server has called
WSAStartup/socket().
git-for-Windows (MSYS2/Cygwin runtime) classifies every inherited handle on
startup by calling NtQueryObject on it. NtQueryObject deadlocks on an
inherited socket/AFD handle. So git never reaches rev-parse, never writes output,
and the server thread blocks forever in fgets on git's stdout pipe.
Three-thread deadlock captured with gdb on the hung process:
# UI request thread — waiting for git output that never comes
ntdll!ZwReadFile -> ReadFile -> msvcrt!fgets
-> git_capture() (git_context.c)
-> cbm_git_context_resolve -> add_git_context_json -> handle_list_projects
-> cbm_mcp_server_handle -> cbm_http_server_run -> http_thread
# the git.exe child — stuck classifying an inherited handle
ntdll!ZwQueryObject (NtQueryObject)
# server main thread — the blocking read on the MCP stdin pipe git inherited/queries
ntdll!ZwReadFile -> ... -> cbm_getline -> cbm_mcp_server_run
Why UI-only: the plain stdio server and the CLI have no listening/AFD socket
handles, so git inherits nothing that trips NtQueryObject.
Reproduction
- On Windows, build with the UI:
make -f Makefile.cbm cbm-with-ui. - Index any two git repos so
list_projectsreturns >1 project. - Run
codebase-memory-mcp --ui=true --port=9749and open the UI (or just
POST /rpc {"method":"tools/call","params":{"name":"list_projects"}}). - The request never returns; the whole UI server stops responding.
tasklist
shows acmd /c git ... rev-parsechild that never exits.
Fix
Spawn git so it inherits only the stdout pipe. See the PR: cbm_popen on
Windows is reimplemented with CreateProcess + STARTUPINFOEX and an explicit
PROC_THREAD_ATTRIBUTE_HANDLE_LIST (stdout write-end + a NUL handle for
stdin/stderr). Nothing else crosses into git → no foreign handle to deadlock on.
The POSIX path is unchanged (popen already sets O_CLOEXEC).
Activity
DeusData commentedon Jul 4, 2026
Thanks for the debugger-backed Windows UI hang report. Triage: high-priority Windows/UI stability under #394/#396.
The root cause is actionable: UI mode creates inheritable socket/AFD handles,
_popenleaks them into git-for-Windows, andlist_projectswedges the single-threaded HTTP server. I see #799 is open for the handle-inheritance fix; review should verify the Windows process-spawn path closes that leak without changing POSIX behavior.test(win): deterministic regression guard for DeusData#798 popen hand…
fix(windows): spawn git without inheriting handles (UI hang)
test(win): full UI-mode hang repro harness for #798 follow-up
Merge pull request #877 from Flipper1994/fix/798-full-ui-repro-harness