Pull requests / #181

#181 Windows: the engine, vision encoder and MCP servers end with the server (closing the window no longer orphans them)

closed · @Apposite245 · 0 commentaires · Sur GitHub

Server & APIModels & quantsWindows

Description

The startup text says *close this window to stop the model*, but on Windows closing the window leaves the model running. The console close ends Python without `atexit` or the shutdown path, and `strata --serve`, `strata-vision` and the MCP servers are plain `Popen` children with nothing tying them to the server, so they keep running and hold their VRAM and RAM until someone finds them in Task Manager. A crash or ending the server from Task Manager does the same. #153 fixes Ctrl+C; this covers every other way the server ends.

## Change
- **`serve/winjob.py`** (new, stdlib ctypes only): `contain(proc)` puts a started child in a job object with `JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE`. The job handle is created without an inheritable handle, so the server holds the only one, and the OS closes it however the server ends, which kills everything in the job. Processes a child starts later (e.g. `npx`, then `node` for an MCP server) join the job automatically.
- **Call sites:** one `contain(self.proc)` after each `Popen`: `StrataEngine.__init__` (so also after an engine restart), `Vision.__init__`, and `StdioTransport.start` in `serve/mcp.py`.
- **Deliberately not in the job: the server process itself.** Otherwise a browser that `--open` launches would be tied to the server and closed with it.
- **Everywhere else, it does nothing:** on non-Windows, if the job can't be created, or if assignment fails, `contain` returns `False` and nothing changes. The existing shutdown path is untouched.

## Tested (Windows 11 25H2, Python 3.13.13)
- **New `serve/test_winjob.py`:** a stand-in server contains a child that starts a grandchild, then gets `TerminateProcess`'d (no `atexit`, no `finally`, the same as closing the window). Both the child and the grandchild end. With the `AssignProcessToJobObject` call stubbed out, the test fails with "the child outlived the server". The test is skipped off Windows.
- **Serve tests:** `python -m unittest serve.test_winjob serve.test_server serve.test_mcp serve.test_detok` gives 68 run, OK (3 skipped by the suites themselves).
- **Not yet tried with a real model loaded:** the test covers the mechanism, not a full `run-<model>.bat` session. I'll confirm on my next run and report back here.

Independent of #153. It touches none of the same lines.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Sur le site

Liens install, modèles, releases.