fix(mcp,model_server,hooks,ingest): Windows subprocess portability#351
Open
Huntehhh wants to merge 1 commit into
Open
fix(mcp,model_server,hooks,ingest): Windows subprocess portability#351Huntehhh wants to merge 1 commit into
Huntehhh wants to merge 1 commit into
Conversation
Replace POSIX-only subprocess patterns with cross-platform equivalents: mcp_server.py (~line 1181): - Guard start_new_session with hasattr(os, setsid); Windows branch uses CREATE_NEW_PROCESS_GROUP | DETACHED_PROCESS via creationflags. - Wrap _log_file open/Popen in try/finally so handle closes on Popen exception. model_server.py (whole file): - Replace hardcoded AF_UNIX socket with platform-conditional: AF_UNIX on POSIX, AF_INET TCP on Windows. Windows path binds 127.0.0.1:0 (OS-assigned port) and writes the port to ~/.truememory/model_server.port for client discovery. - Guard SIGHUP registration with hasattr(signal, SIGHUP) — absent on Windows. - Idle-checker dummy wakeup uses AF_UNIX or AF_INET matching server bind. model_client.py (whole file): - Mirror server socket logic: _get_server_address() returns SOCK_PATH string on POSIX and (127.0.0.1, port) on Windows via PORT_PATH sidecar file. - _start_server Popen: same start_new_session / creationflags guard. - _send_request: constructs AF_UNIX or AF_INET socket depending on platform. hooks/core.py (ps/pgrep guards): - Add import psutil at module top. - _pid_is_alive: replace subprocess.run([ps, ...]) with psutil.Process(). - _count_active_ingest_processes: replace subprocess.run([pgrep, ...]) with psutil.process_iter([cmdline,status]). ingest/cli.py:308: - Same start_new_session / creationflags guard for cascade Popen. ingest/hooks/session_start.py:~226: - Same start_new_session / creationflags guard for drain Popen + try/finally for _log_file. Did NOT touch _HAS_FCNTL block (agent-A buildingjoshbetter#345 territory). tests/test_windows_subprocess_portability.py (new): - 22 tests covering all six modified regions. tests/test_cli_help.py (lines 94-98, 137-152): - Swap bare console-script shim invocations for [sys.executable, -m, ...] to bypass Windows Defender ASR rule 01443614 on low-prevalence hosts. Co-Authored-By: claude-sonnet-4-6 <wontreply@getfucked.ai>
This was referenced May 17, 2026
Open
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Replaces six POSIX-only subprocess patterns with cross-platform equivalents so TrueMemory runs correctly on Windows. Also fixes a
_log_filehandle-leak and swaps two ASR-blocked test invocations withpython.exe -mequivalents.Changes per file
truememory/mcp_server.py(~line 1181 — backlog drainer Popen)start_new_session=Trueguarded withhasattr(os, "setsid")(POSIX probe). Windows branch usescreationflags=CREATE_NEW_PROCESS_GROUP | DETACHED_PROCESS._log_fileopen/Popen wrapped intry/finallyso the file handle closes even ifPopen()raises.truememory/model_server.py(whole file)socket.AF_UNIXwith a platform-conditional: AF_UNIX on POSIX, AF_INET TCP on Windows.127.0.0.1:0(OS-assigned port), writes the port to~/.truememory/model_server.portas a sidecar discovery file.SIGHUPregistration guarded withhasattr(signal, "SIGHUP")— the signal doesn't exist on Windows.truememory/model_client.py(whole file)_get_server_address()returns the SOCK_PATH string on POSIX or("127.0.0.1", port)on Windows by readingPORT_PATH._start_serverPopen: samestart_new_session/creationflagsguard._send_request: constructsAF_UNIXorAF_INETsocket to match platform.truememory/hooks/core.py(ps/pgrep guards)import psutiladded at module top (already a dep)._pid_is_alive: replacessubprocess.run(["ps", ...])withpsutil.Process().status()._count_active_ingest_processes: replacessubprocess.run(["pgrep", ...])withpsutil.process_iter(["cmdline","status"]).truememory/ingest/cli.py:308start_new_session/creationflagsguard for cascade Popen.truememory/ingest/hooks/session_start.py:~226try/finallyfor drain Popen_log_file. The_HAS_FCNTLblock at lines 1-40 is untouched (agent-A fix(hooks): guard fcntl import on Windows — _shared + session_start #345 territory).tests/test_windows_subprocess_portability.py(new — 22 tests)tests/test_cli_help.py(lines 94-98, 137-152)test_help_via_console_script_does_not_hang: replaced["truememory-mcp", "--help"]with[sys.executable, "-m", "truememory.mcp_server", "--help"].test_ingest_version_flag_exits_cleanly: replaced[shutil.which("truememory-ingest"), "--version"]with[sys.executable, "-m", "truememory.ingest.cli", "--version"].python.exebinary, bypassing Windows Defender ASR rule 01443614 which blocks low-prevalence console-script.exeshims.Merge ordering
Depends on:
os.WNOHANGguard — agent-A) —mcp_server.py:1181fix lands cleanly on top of the async-handler conversion._HAS_FCNTLguard — agent-A) —session_start.py:~226fix intentionally leaves the bareimport fcntlat line 24 intact; after fix(hooks): guard fcntl import on Windows — _shared + session_start #345 lands that becomes the guarded version.Clean mechanical rebase is expected on merge of either; zero semantic conflicts with #344, #345, #346, #347, #348, #349, or #350.
Test plan
python -m pytest tests/test_windows_subprocess_portability.py— 22/22 pass on Windowstest_help_via_console_script_does_not_hang— passes viapython -mpathtest_ingest_version_flag_exits_cleanly— passes viapython -mpathpython -c "import truememory.model_server; import truememory.model_client; import truememory.hooks.core"— clean on Windows and POSIXGenerated with Claude Code