Repository navigation
Conversation
modelopt-mcp runs as a stdio MCP server, so its stdin is the MCP transport. The three modelopt-launcher calls in submit_job (Docker Popen, Slurm run, dry-run run) left stdin unset, and the child inherited it. Pass stdin=subprocess.DEVNULL at those calls. Add a test that runs the real submit_job_impl and subprocess calls with data waiting on stdin and checks that a stand-in launcher reads 0 bytes. Fixes NVIDIA#2551 Signed-off-by: Som Tripathi <somtri@iastate.edu>
|
No actionable comments were generated in the recent review.
|
| Layer / File(s) | Summary |
|---|---|
Set launcher subprocess stdin tools/mcp/modelopt_mcp/bridge.py |
Docker, Slurm, and dry-run launcher subprocesses now receive stdin=subprocess.DEVNULL. |
Test launcher stdin isolation tools/mcp/tests/test_bridge.py |
A parameterized regression test checks that child processes read zero bytes from stdin for dry-run, Slurm, and Docker submissions. |
Estimated code review effort: 2 (Simple) | ~10 minutes
Change: Bug fix · Severity of issue fixed: Medium
Suggested reviewers: chenhanyu
Merge Risk: 
Minimal · up to 2b89d
-
Launcher subprocesses no longer inherit server stdin. No merge-blocking issue was identified.
Pre-merge checks: 
6
-
Full details: Linked Issues check
-
Explanation
Issue
#2551requires the threemodelopt-launchersubprocesses to usestdin=subprocess.DEVNULL: DockerPopen, Slurmrun, and dry-runrun. The whole-PR diff adds this argument at all three call sites intools/mcp/modelopt_mcp/bridge.py. The new parametrized test coversdry_run,slurm, anddockermodes and asserts that the child reads zero bytes from the server stdin.
Full details: Out of Scope Changes check
-
Explanation
The PR changes only launcher stdin handling and adds a regression test for issue
#2551. The test directly exercises the affected submission modes. No unrelated production behavior, public API, or result field changes are present in the reviewed diff.
Full details: Docstring Coverage
-
Explanation
Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff with cyclomatic complexity of at least 2. Documentation-only edits and deletions within surviving functions are included; unchanged diff context and fully deleted functions are excluded. Analyzed 3 functions across 2 files.
Full details: Security Anti-Patterns
-
Explanation
PASS. The PR changes only
tools/mcp/modelopt_mcp/bridge.pyand its test. Added code only setsstdin=subprocess.DEVNULLand adds stdin-isolation test logic. The diff adds notorch.load(..., weights_only=False),allow_pickle=True, hardcodedtrust_remote_code=True, external-inputeval/exec,# noseccomments, or dependency manifest changes. Existing# noseccomments inbridge.pyare unchanged from the base revision.
-
Finishing Touches
-
🧪 Generate unit tests (beta)
-
- Create a new PR
-
- Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts
Comment @coderabbitai help to get the list of available commands.
|
Thanks for the contribution! This PR now has merge conflicts with We've added the |
…in-devnull Signed-off-by: Som Tripathi <somtri@iastate.edu> # Conflicts: # tools/mcp/tests/test_bridge.py
|
Merged the latest |
What does this PR do?
Type of change: Bug fix
Fixes #2551.
When
modelopt-mcpruns as a stdio MCP server, its stdin is the MCP transport. The threemodelopt-launchercalls insubmit_jobleavestdinunset, so each child inherits that pipe. On Windows, a real MCP client callingsubmit_job(dry_run=True)then waits for the 60 s timeout and getsdry_run_timeout(details under Testing).This PR passes
stdin=subprocess.DEVNULLat those three calls: the DockerPopen, the Slurmrunand the dry-runrun. The other subprocess calls inbridge.py(git, docker, ssh, nemo, gh) are unchanged. They were not observed to hang and were not tested.sshforwards inherited stdin unless-nis set. Whether that matters here was not checked.Usage
No change to the arguments or result fields of any tool.
Testing
One new parametrized test,
test_launcher_children_do_not_inherit_server_stdin(casesdry_run,slurm,docker), runs the realsubmit_job_impland the realsubprocess.runandPopen. The test process's stdin is a pipe that holds 5 bytes. A stand-in launcher, a short Python script, writes how many bytes it could read from stdin. The test expects 0.stdin=lines fails only that case.tools/mcp/tests/test_bridge.pyon Windows 11: 66 passed, 3 failed. The 3 failures aretest_provision_ssh_*. On the same machine they fail the same way on main without this change (63 passed, 3 failed). CI was not run.Manual check on Windows 11, Python 3.12, mcp 1.30.0, with a stdio MCP client calling
submit_jobwithdry_run=Trueonexamples/smoke/nvidia_smi.yaml:dry_run_timeoutafter 60.0 s, in 2 of 2 runs.ok: true,exit_code: 0, in under 7 s on repeat runs (4.3 s in the last three). The first run after setup was slower.What this does not show: the cause of the hang (a pipe that nothing reads did not reproduce it, only the server's own live stdin did), Linux or macOS behavior, the live Docker and Slurm paths, or the
uv run --with-editablemanaged-checkout path. The new test checks that the child does not read the server's stdin. It does not reproduce the hang.Before your PR is "Ready for review"
Make sure you read and follow Contributor guidelines and your commits are signed (
git commit -s -S).Make sure you read and follow the Security Best Practices (e.g. avoiding hardcoded
trust_remote_code=True,torch.load(..., weights_only=False),pickle, etc.).CONTRIBUTING.md: N/Atools/mcpis not listed inCHANGELOG.rst)/claude reviewhas not been run on this PR)Additional Information
An earlier attempt, #2557, added the same three
stdin=arguments with tests that mocksubprocess. Its author closed it without a human review. This PR adds a test that runs the real subprocess path.Summary by CodeRabbit