Skip to content

Conversation

@dsarno
Copy link
Owner

@dsarno dsarno commented Dec 31, 2025

Motivation

  • WaitForHttpServerAcceptingConnectionsAsync could leave ConnectAsync tasks unobserved causing later task exceptions/noise.
  • The handshake (pidfile + instance token) was persisted before launching the terminal, leaving stale handshake state if Process.Start failed.
  • A Unity-launched local server could be orphaned when the user switched away from HTTP Local or on shutdown.
  • Unix process-arg probing could treat error output as valid args when ps failed, weakening PID verification.

Description

  • Observe pending TCP connect tasks: await completed connectTask when it finishes and attach a continuation to consume exceptions when it does not complete (WaitForHttpServerAcceptingConnectionsAsync change).
  • Persist handshake only after the terminal launch succeeds by moving StoreLocalHttpServerHandshake to after Process.Start.
  • Add a new API StopManagedLocalHttpServer() and a TryGetPortFromPidFilePath helper, and extend StopLocalHttpServerInternal with portOverride/allowNonLocalUrl to support deterministic managed stops even when transport selection changed.
  • Tighten Unix process args probing to require ExecPath.TryRun success (or non-empty stdout) before using ps output, and update shutdown cleanup to attempt stopping Unity-managed servers regardless of current transport selection.

Testing

  • No automated tests were run.

Codex Task

Summary by CodeRabbit

Release Notes

  • Bug Fixes
    • Improved reliability of local HTTP server shutdown and cleanup during editor termination
    • Enhanced connection readiness detection with more robust verification logic
    • Better handling of managed local HTTP server shutdown scenarios

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai
Copy link

coderabbitai bot commented Dec 31, 2025

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Walkthrough

The PR introduces a distinction between user-selected and Unity-managed local HTTP servers in the MCP editor services. It adds a new StopManagedLocalHttpServer() method to stop servers via handshake/pidfile, refactors shutdown logic to call different stop methods based on server selection state, and improves connection readiness checks with enhanced error handling.

Changes

Cohort / File(s) Summary
Interface Updates
MCPForUnity/Editor/Services/IServerManagementService.cs
Added method signature bool StopManagedLocalHttpServer() with XML documentation to support stopping Unity-managed local HTTP servers independent of transport selection.
Server Management Implementation
MCPForUnity/Editor/Services/ServerManagementService.cs
Implemented StopManagedLocalHttpServer() public method; refactored StopLocalHttpServerInternal() signature to accept optional portOverride and allowNonLocalUrl parameters; added TryGetPortFromPidFilePath() helper to extract port from pid filename; removed duplicate terminal-launch block in StartLocalHttpServer; added defensive check to TryGetUnixProcessArgs.
Shutdown Logic Refactoring
MCPForUnity/Editor/Services/McpEditorShutdownCleanup.cs
Reworked OnEditorQuitting to always evaluate HTTP-related block instead of early-returning when HTTP unselected; calls StopLocalHttpServer if user-selected local HTTP, or StopManagedLocalHttpServer if Unity-managed; updated condition logic and exception messaging.
Connection Readiness Verification
MCPForUnity/Editor/Windows/Components/Connection/McpConnectionSection.cs
Enhanced HTTP local server readiness check to await connection task completion and verify TcpClient.Connected state; added exception swallowing during await; added continuation for non-completing connection tasks to observe exceptions.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~22 minutes

Poem

🐰✨ A managed server born of handshake's kiss,
Distinct from those the users dismiss,
When Editor quits, the cleanup flows,
Port extraction from pidfiles glows,
Connection checks await their fate,
Unix and TCP cooperate! 🔌

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 33.33% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'Fix local HTTP server lifecycle and TCP connect observation' directly corresponds to the main changes: addressing HTTP server lifecycle issues (handshake persistence, managed server stopping) and TCP connection task observation fixes in McpConnectionSection.

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@dsarno
Copy link
Owner Author

dsarno commented Dec 31, 2025

@coderabbitai review

@coderabbitai
Copy link

coderabbitai bot commented Dec 31, 2025

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@dsarno dsarno marked this pull request as ready for review December 31, 2025 17:00
@dsarno dsarno merged commit 8dae8e2 into http-improvements Dec 31, 2025
4 checks passed
@greptile-apps
Copy link

greptile-apps bot commented Dec 31, 2025

Greptile Summary

This PR improves local HTTP server lifecycle management and fixes unobserved task exceptions. Key changes include moving handshake persistence to after Process.Start succeeds (preventing stale state on launch failure), observing pending TCP ConnectAsync tasks to eliminate unobserved exceptions, adding StopManagedLocalHttpServer() API for deterministic shutdown when transport selection changes, and tightening Unix process validation to reject error output from failed ps commands.

Key Improvements:

  • Fixed unobserved task exceptions in WaitForHttpServerAcceptingConnectionsAsync by awaiting completed tasks and attaching continuations to observe exceptions from unfinished tasks
  • Handshake (pidfile + token) now persisted after terminal launch succeeds, eliminating stale state if Process.Start fails
  • New StopManagedLocalHttpServer() API prevents orphaned servers when users switch transports or on shutdown
  • Unix process validation now requires ExecPath.TryRun success or non-empty stdout before trusting ps output
  • read_console default behavior improved to cap at 200 entries (performance fix)

Issue Found:

  • ServerManagementService.cs:668-674 - Missing return false after detecting pidfile PID is Unity Editor, allowing fallthrough to port-based heuristics

Confidence Score: 4/5

  • This PR is safe to merge with one logic issue requiring attention
  • Score reflects solid improvements to server lifecycle and task exception handling, but one missing return statement in the Unity PID detection path could allow unintended fallthrough to port-based termination heuristics
  • Pay close attention to MCPForUnity/Editor/Services/ServerManagementService.cs - the missing return statement at line 674 should be added to prevent fallthrough when pidfile PID matches Unity Editor

Important Files Changed

Filename Overview
MCPForUnity/Editor/Services/McpEditorShutdownCleanup.cs Enhanced shutdown logic to attempt Unity-managed server stop regardless of transport selection
MCPForUnity/Editor/Services/ServerManagementService.cs Fixed handshake persistence timing, added TryGetPortFromPidFilePath helper, improved Unix process validation, removed dead LocalHttpServerProcess code
MCPForUnity/Editor/Windows/Components/Connection/McpConnectionSection.cs Fixed unobserved TCP ConnectAsync tasks by awaiting completed task and attaching continuation to unfinished tasks

Sequence Diagram

sequenceDiagram
    participant User
    participant Unity as Unity Editor
    participant ServerMgmt as ServerManagementService
    participant Terminal
    participant HTTPServer as HTTP Server Process
    participant Shutdown as McpEditorShutdownCleanup
    participant TCP as TCP Connection Check

    Note over User,HTTPServer: Start Local HTTP Server
    User->>Unity: Click "Start Server"
    Unity->>ServerMgmt: StartLocalHttpServer()
    ServerMgmt->>ServerMgmt: ClearLocalServerPidTracking()
    ServerMgmt->>ServerMgmt: Generate instanceToken + pidFilePath
    ServerMgmt->>Terminal: Process.Start(launchCommand)
    Terminal->>HTTPServer: Launch server process
    ServerMgmt->>ServerMgmt: StoreLocalHttpServerHandshake(pidFilePath, token)
    Note right of ServerMgmt: Handshake persisted AFTER<br/>successful Process.Start

    Note over User,TCP: Wait for Server Ready
    Unity->>TCP: WaitForHttpServerAcceptingConnectionsAsync()
    loop Poll until timeout
        TCP->>HTTPServer: TcpClient.ConnectAsync()
        alt Connection completes first
            TCP->>TCP: await connectTask
            TCP-->>Unity: true (if connected)
        else Timeout completes first
            TCP->>TCP: Attach continuation to observe exceptions
            Note right of TCP: connectTask.ContinueWith(t => _ = t.Exception)
        end
    end

    Note over User,HTTPServer: Shutdown Scenarios
    alt User switches transport OR quits Unity
        Unity->>Shutdown: OnEditorQuitting()
        alt HTTP Local selected
            Shutdown->>ServerMgmt: StopLocalHttpServer()
            ServerMgmt->>ServerMgmt: Read pidFilePath from handshake
            ServerMgmt->>ServerMgmt: Validate PID + token
            ServerMgmt->>HTTPServer: TerminateProcess(pid)
        else HTTP Local NOT selected
            Shutdown->>ServerMgmt: StopManagedLocalHttpServer()
            ServerMgmt->>ServerMgmt: TryGetPortFromPidFilePath()
            ServerMgmt->>ServerMgmt: StopLocalHttpServerInternal(portOverride, allowNonLocalUrl=true)
            Note right of ServerMgmt: Deterministic stop even when<br/>transport selection changed
            ServerMgmt->>HTTPServer: TerminateProcess(pid)
        end
    end

    Note over ServerMgmt,HTTPServer: Unix Process Validation Improvement
    ServerMgmt->>ServerMgmt: TryGetUnixProcessArgs(pid)
    ServerMgmt->>ServerMgmt: ExecPath.TryRun("ps", args)
    alt ps command fails AND stdout empty
        ServerMgmt-->>ServerMgmt: return false (reject)
        Note right of ServerMgmt: Prevents treating error<br/>output as valid args
    else ps succeeds OR stdout non-empty
        ServerMgmt-->>ServerMgmt: return args (accept)
    end
Loading

Copy link

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Additional Comments (1)

  1. MCPForUnity/Editor/Services/ServerManagementService.cs, line 668-674 (link)

    logic: missing return false after warning - when pidfile PID is Unity Editor, should return immediately instead of falling through to port-based heuristics

5 files reviewed, 1 comment

Edit Code Review Agent Settings | Greptile

@coderabbitai coderabbitai bot mentioned this pull request Jan 1, 2026
@dsarno dsarno deleted the codex/fix-unobserved-connectasync-tasks branch January 2, 2026 19:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants