Skip to content

Launch the local HTTP server without inheriting the editor's handles - #51

Merged
vbucc merged 2 commits into
mainfrom
fix/issue-50-server-launch-handle-inheritance
Sep 25, 2026
Merged

vbucc merged 2 commits into
mainfrom
fix/issue-50-server-launch-handle-inheritance

Conversation

@vbucc

@vbucc vbucc commented Sep 25, 2026

Copy link
Copy Markdown
Collaborator

Description

On Windows, the local HTTP server started from an editor kept that editor's Logs/Editor.log locked for the server's whole life. Every later editor of the project then fell back to the machine-global Editor.log (#50).

The cause is Mono's Process.Start: it calls CreateProcessW with bInheritHandles hard-coded TRUE. So the launch process (cmd, then uvx, uv and python) got a copy of every inheritable handle the editor held, including its open log.

The server launch now goes through ServerProcessLauncher, which makes the same CreateProcessW call with inheritance off.

Fixes #50

Type of Change

  • Bug fix (non-breaking change that fixes an issue)
  • Test update

Changes Made

  • New MCPForUnity/Editor/Services/Server/ServerProcessLauncher.cs, which on Windows makes Mono's CreateProcessW call with these differences:
    • bInheritHandles = FALSE.
    • No std handles are passed, so cmd uses its own hidden console's.
    • The process is created suspended, so Process.GetProcessById gets its handle before the process can exit. That handle is then made non-inheritable, as Process.Start's is.
    • Unchanged from Mono: the command line and the environment block, built from EnvironmentVariables in the same order.
    • Off Windows it is Process.Start: Mono closes descriptors above 2 in a POSIX child, so nothing leaks there.
    • Its contract holds on every platform: UseShellExecute, redirects, UserName and ArgumentList throw NotSupportedException instead of being silently dropped.
  • ServerManagementService.StartLocalHttpServer: a one-line change to call the launcher.
  • New ServerProcessLauncherTests (Windows cases use Assert.Ignore elsewhere):
    • The launched process holds no copy of an inheritable editor handle, checked with the Restart Manager. Red on Process.Start.
    • The returned handle is not inheritable. Red without the SetHandleInformation call.
    • cd & set output is identical to Process.Start's: working directory and environment.
    • Unsupported fields throw NotSupportedException.
  • Version bumped to 10.2.0-fork.2.

Behaviour changes (Windows)

  • The server no longer inherits any editor handle. This is the fix.
  • cmd's own messages go to its hidden console, not to the editor's std handles, which a GUI editor does not have. The server's output still goes to the launch log through the existing < NUL >> log 2>&1.
  • A start info whose EnvironmentVariables was never touched now passes a snapshot of the editor's environment, without Windows' hidden =C: drive entries. The production launch always touches it (the uv PATH prepend), so only the characterization fake (cmd /c exit) takes this path.

Compatibility / Package Source

  • Unity version(s) tested: 6000.5.5f1 (Windows 11)
  • Package source used: file: (TestProjects/UnityMCPTests)

Testing

  • Unity EditMode tests
    • Local gate: python tools/local_harness.py --legs editmode gave 1035/1114 passed, 0 failed.
    • Direct batchmode run of ServerProcessLauncherTests, ServerManagementServiceCharacterizationTests and TerminalLauncherTests: 72/72 passed.
  • Python tests: not applicable, Server/ is untouched.

Related Issues

Fixes #50

Additional Notes

  • A server that is already running keeps its inherited handle until it is restarted from an editor that has this version.
  • An IDE started from Unity (for example VS Code, through com.unity.ide.visualstudio) can still hold the log the same way. That launch is outside this package.

🤖 Generated with Claude Code

https://claude.ai/code/session_018mVoikeBS5RijnEmvTr8RR

vbucc and others added 2 commits September 24, 2026 22:38
On Windows, Mono's Process.Start calls CreateProcessW with bInheritHandles
hard-coded TRUE, so the server's launch process (cmd, then uvx, uv and
python) got a copy of every inheritable handle the editor held, including
its open Logs/Editor.log. The server outlives the editor, so that log stayed
locked and every later editor of the project fell back to the machine-global
Editor.log (#50).

ServerProcessLauncher makes the CreateProcessW call Mono makes with
inheritance off: same command line and environment block, created suspended
so Process.GetProcessById gets its handle before the process can exit, with
that handle made non-inheritable as Process.Start's is. It passes no std
handles, so cmd uses its own hidden console's. Unsupported ProcessStartInfo
fields throw NotSupportedException on every platform; off Windows it is
Process.Start (Mono closes descriptors above 2 in a POSIX child).

Tests: the launched process holds no copy of an inheritable editor handle
(red on Process.Start), the returned handle is not inheritable (red without
the SetHandleInformation call), the launch matches Process.Start's
environment and working directory, and the contract rejects unsupported fields.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018mVoikeBS5RijnEmvTr8RR
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018mVoikeBS5RijnEmvTr8RR
@vbucc
vbucc merged commit 4d0e752 into main Sep 25, 2026
0 of 2 checks passed
@vbucc
vbucc deleted the fix/issue-50-server-launch-handle-inheritance branch September 25, 2026 02:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Windows: the local HTTP server inherits the launching editor's handles and keeps its Logs/Editor.log locked

1 participant