René's URL Explorer Experiment


Title: Fix stdio client shutdown bugs and rebuild the stdio test suite by maxisbey · Pull Request #2773 · modelcontextprotocol/python-sdk · GitHub

Open Graph Title: Fix stdio client shutdown bugs and rebuild the stdio test suite by maxisbey · Pull Request #2773 · modelcontextprotocol/python-sdk

X Title: Fix stdio client shutdown bugs and rebuild the stdio test suite by maxisbey · Pull Request #2773 · modelcontextprotocol/python-sdk

Description: The stdio test suite has a long flake history (#1775, #1158, #559, #401). Auditing it surfaced real bugs in the client transport's shutdown path. This PR fixes the transport and rebuilds the stdio tests so they are deterministic. Motivation and Context Shutdown bugs fixed (each has a regression test that fails on main): Cancelling stdio_client could deadlock shutdown forever. Cleanup was not shielded, so a cancelled client fell into anyio's Process.aclose(), which waits for all pipes to close — and a server with a child of its own (npx ..., uv run ...) holds the pipes open indefinitely. Tree-kill silently did nothing when the server process had already died. os.getpgid() raises once the leader is reaped, leaking every surviving child. The group is now killed via the spawn-time pgid. "Did the server exit?" actually checked "did all pipes close?". process.wait() is pipe-gated on asyncio 3.11+, so a server that exited promptly but left a background child running was misclassified as hung and its whole tree killed. The wait now keys on returncode, which reflects process death alone. The Windows fallback's wait() could not be cancelled. It ran in a non-cancellable worker thread, so the timeout around it could never fire and escalation was unreachable. I/O on a dead server leaked raw backend exceptions. Writing leaked ConnectionResetError; reading leaked BrokenResourceError. Both now surface as clean session closure. Fixes #1960. A killed process was never reaped. The unclosed subprocess transport leaked a ResourceWarning into whatever ran next. The whole sequence now lives in one cancellation-shielded function with named timeouts: close stdin → grace period keyed on process death → terminate tree → bounded wait → kill tree. See docs/migration.md. Test rebuild: Transport logic (framing, parse errors, escalation timing, shutdown edges) now runs in process against a small fake process. No sleeps, no polling; escalation timing is pinned on trio's virtual clock. Real subprocesses remain only where the OS itself is under test: group kill semantics (including a dead leader), SIGKILL after an ignored SIGTERM, exec failure. 5 tests, down from 14. New tests/transports/stdio/ suite pins the end-to-end lifecycle on both platforms: clean exit without escalation, cancellation kills the whole tree, stderr routing, and the child-survival policy. Deleted the tee-based tests and test_1027_win_unreachable_cleanup.py (their properties are re-pinned above). test_552_windows_hang.py now asserts real outcomes instead of swallowing exceptions. How Has This Been Tested? 100% line+branch coverage; the stdio surface runs in ~5s (was ~10.8s) Every fix verified two ways: its regression test fails on main, and the OS-level claims were verified empirically on asyncio and trio 600 clean full-suite runs on GitHub-hosted runners (300 Windows / 300 Ubuntu, Python 3.10–3.14), plus stress runs under xdist and CPU saturation: zero failures, zero orphan processes Breaking Changes terminate_windows_process (deprecated) is removed; terminate_windows_process_tree no longer takes the unused timeout_seconds. POSIX: a server that exits cleanly no longer has its surviving background children killed (the old kill was a side effect of bug 3). A server that ignores shutdown still gets its whole tree killed. Windows: surviving job members are reaped deterministically at shutdown rather than at GC time. Details in docs/migration.md. Types of changes Bug fix (non-breaking change which fixes an issue) Breaking change (fix or feature that would cause existing functionality to change) Checklist I have read the MCP Documentation My code follows the repository's style guidelines New and existing tests pass locally I have added appropriate error handling I have added or updated documentation as needed Additional context Two known limitations are documented in code rather than fixed: The shielded shutdown holds against anyio-level cancellation, but a native task.cancel() delivered mid-cleanup can still abort it (no backend-neutral way to refuse native cancellation). On Windows, children spawned before the Job Object assignment completes are outside the job (pre-existing; a CREATE_SUSPENDED spawn is the follow-up if it bites). AI Disclaimer

Open Graph Description: The stdio test suite has a long flake history (#1775, #1158, #559, #401). Auditing it surfaced real bugs in the client transport's shutdown path. This PR fixes the transport and rebuilds the st...

X Description: The stdio test suite has a long flake history (#1775, #1158, #559, #401). Auditing it surfaced real bugs in the client transport's shutdown path. This PR fixes the transport and rebuilds th...

Opengraph URL: https://github.com/modelcontextprotocol/python-sdk/pull/2773

X: @github

direct link

Domain: github.com

route-pattern/:user_id/:repository/pull/:id/files(.:format)
route-controllerpull_requests
route-actionfiles
fetch-noncev2:efd41d28-169b-b3e4-43e8-faa40b3ef1b1
current-catalog-service-hashae870bc5e265a340912cde392f23dad3671a0a881730ffdadd82f2f57d81641b
request-idCB16:155BEF:8D1D95:BF71DF:6A5A85CB
html-safe-nonce772ec9a86ec901b238cc2de9d5c0bffee323effe293ae3eff7884c29643d5497
visitor-payloadeyJyZWZlcnJlciI6IiIsInJlcXVlc3RfaWQiOiJDQjE2OjE1NUJFRjo4RDFEOTU6QkY3MURGOjZBNUE4NUNCIiwidmlzaXRvcl9pZCI6IjQ4NTMzMzg5MTgwMjYyOTU3OSIsInJlZ2lvbl9lZGdlIjoiaWFkIiwicmVnaW9uX3JlbmRlciI6ImlhZCJ9
visitor-hmac29f60b08f8b248fa8e4a592d375cdb32f0c8594cdc8e9b46bdbbbd5c3ddbaf46
hovercard-subject-tagpull_request:3796466322
github-keyboard-shortcutsrepository,pull-request-list,pull-request-conversation,pull-request-files-changed,copilot
google-site-verificationApib7-x98H0j5cPqHWwSMm6dNU4GmODRoqxLiDzdx9I
octolytics-urlhttps://collector.github.com/github/collect
analytics-location///pull_requests/show/files
fb:app_id1401488693436528
apple-itunes-appapp-id=1477376905, app-argument=https://github.com/modelcontextprotocol/python-sdk/pull/2773/files
twitter:imagehttps://avatars.githubusercontent.com/u/224885523?s=400&v=4
twitter:cardsummary_large_image
og:imagehttps://avatars.githubusercontent.com/u/224885523?s=400&v=4
og:image:altThe stdio test suite has a long flake history (#1775, #1158, #559, #401). Auditing it surfaced real bugs in the client transport's shutdown path. This PR fixes the transport and rebuilds the st...
og:site_nameGitHub
og:typeobject
hostnamegithub.com
expected-hostnamegithub.com
None922bdba685ea48400234d557977f0e32d9adbae6f5125725b4f48cacc6801106
turbo-cache-controlno-preview
diff-viewunified
go-importgithub.com/modelcontextprotocol/python-sdk git https://github.com/modelcontextprotocol/python-sdk.git
octolytics-dimension-user_id182288589
octolytics-dimension-user_loginmodelcontextprotocol
octolytics-dimension-repository_id862584018
octolytics-dimension-repository_nwomodelcontextprotocol/python-sdk
octolytics-dimension-repository_publictrue
octolytics-dimension-repository_is_forkfalse
octolytics-dimension-repository_network_root_id862584018
octolytics-dimension-repository_network_root_nwomodelcontextprotocol/python-sdk
turbo-body-classeslogged-out env-production page-responsive full-width
disable-turbotrue
browser-stats-urlhttps://api.github.com/_private/browser/stats
browser-errors-urlhttps://api.github.com/_private/browser/errors
release7c8a44665d760d73ead7e85d8f88b299152aa681
ui-targetfull
theme-color#1e2327
color-schemelight dark

Links:

Skip to contenthttps://github.com/modelcontextprotocol/python-sdk/pull/2773/files#start-of-content
https://github.com/
Sign in https://github.com/login?return_to=https%3A%2F%2Fgithub.com%2Fmodelcontextprotocol%2Fpython-sdk%2Fpull%2F2773%2Ffiles
GitHub CopilotWrite better code with AIhttps://github.com/features/copilot
GitHub Copilot appDirect agents from issue to mergehttps://github.com/features/ai/github-app
MCP RegistryNewIntegrate external toolshttps://github.com/mcp
ActionsAutomate any workflowhttps://github.com/features/actions
CodespacesInstant dev environmentshttps://github.com/features/codespaces
IssuesPlan and track workhttps://github.com/features/issues
Code ReviewManage code changeshttps://github.com/features/code-review
GitHub Advanced SecurityFind and fix vulnerabilitieshttps://github.com/security/advanced-security
Code securitySecure your code as you buildhttps://github.com/security/advanced-security/code-security
Secret protectionStop leaks before they starthttps://github.com/security/advanced-security/secret-protection
Why GitHubhttps://github.com/why-github
Documentationhttps://docs.github.com
Bloghttps://github.blog
Changeloghttps://github.blog/changelog
Marketplacehttps://github.com/marketplace
View all featureshttps://github.com/features
Enterpriseshttps://github.com/enterprise
Small and medium teamshttps://github.com/team
Startupshttps://github.com/enterprise/startups
Nonprofitshttps://github.com/solutions/industry/nonprofits
App Modernizationhttps://github.com/solutions/use-case/app-modernization
DevSecOpshttps://github.com/solutions/use-case/devsecops
DevOpshttps://github.com/solutions/use-case/devops
CI/CDhttps://github.com/solutions/use-case/ci-cd
View all use caseshttps://github.com/solutions/use-case
Healthcarehttps://github.com/solutions/industry/healthcare
Financial serviceshttps://github.com/solutions/industry/financial-services
Manufacturinghttps://github.com/solutions/industry/manufacturing
Governmenthttps://github.com/solutions/industry/government
View all industrieshttps://github.com/solutions/industry
View all solutionshttps://github.com/solutions
AIhttps://github.com/resources/articles?topic=ai
Software Developmenthttps://github.com/resources/articles?topic=software-development
DevOpshttps://github.com/resources/articles?topic=devops
Securityhttps://github.com/resources/articles?topic=security
View all topicshttps://github.com/resources/articles
Customer storieshttps://github.com/customer-stories
Events & webinarshttps://github.com/resources/events
Ebooks & reportshttps://github.com/resources/whitepapers
Business insightshttps://github.com/solutions/executive-insights
GitHub Skillshttps://skills.github.com
Documentationhttps://docs.github.com
Customer supporthttps://support.github.com
Community forumhttps://github.com/orgs/community/discussions
Trust centerhttps://github.com/trust-center
Partnershttps://github.com/partners
View all resourceshttps://github.com/resources
GitHub SponsorsFund open source developershttps://github.com/open-source/sponsors
Security Labhttps://securitylab.github.com
Maintainer Communityhttps://maintainers.github.com
Acceleratorhttps://github.com/open-source/accelerator
GitHub Starshttps://stars.github.com
Archive Programhttps://archiveprogram.github.com
Topicshttps://github.com/topics
Trendinghttps://github.com/trending
Collectionshttps://github.com/collections
Enterprise platformAI-powered developer platformhttps://github.com/enterprise
GitHub Advanced SecurityEnterprise-grade security featureshttps://github.com/security/advanced-security
Copilot for BusinessEnterprise-grade AI featureshttps://github.com/features/copilot/copilot-business
Premium SupportEnterprise-grade 24/7 supporthttps://github.com/enterprise/premium-support
Pricinghttps://github.com/pricing
Search syntax tipshttps://docs.github.com/search-github/github-code-search/understanding-github-code-search-syntax
documentationhttps://docs.github.com/search-github/github-code-search/understanding-github-code-search-syntax
Sign in https://github.com/login?return_to=https%3A%2F%2Fgithub.com%2Fmodelcontextprotocol%2Fpython-sdk%2Fpull%2F2773%2Ffiles
Sign up https://github.com/signup?ref_cta=Sign+up&ref_loc=header+logged+out&ref_page=%2F%3Cuser-name%3E%2F%3Crepo-name%3E%2Fpull_requests%2Fshow%2Ffiles&source=header-repo&source_repo=modelcontextprotocol%2Fpython-sdk
Reloadhttps://github.com/modelcontextprotocol/python-sdk/pull/2773/files
Reloadhttps://github.com/modelcontextprotocol/python-sdk/pull/2773/files
Reloadhttps://github.com/modelcontextprotocol/python-sdk/pull/2773/files
Please reload this pagehttps://github.com/modelcontextprotocol/python-sdk/pull/2773/files
modelcontextprotocol https://github.com/modelcontextprotocol
python-sdkhttps://github.com/modelcontextprotocol/python-sdk
Notifications https://github.com/login?return_to=%2Fmodelcontextprotocol%2Fpython-sdk
Fork 3.7k https://github.com/login?return_to=%2Fmodelcontextprotocol%2Fpython-sdk
Star 23.6k https://github.com/login?return_to=%2Fmodelcontextprotocol%2Fpython-sdk
Code https://github.com/modelcontextprotocol/python-sdk
Issues 256 https://github.com/modelcontextprotocol/python-sdk/issues
Pull requests 303 https://github.com/modelcontextprotocol/python-sdk/pulls
Actions https://github.com/modelcontextprotocol/python-sdk/actions
Projects https://github.com/modelcontextprotocol/python-sdk/projects
Models https://github.com/modelcontextprotocol/python-sdk/models
Security and quality 6 https://github.com/modelcontextprotocol/python-sdk/security
Insights https://github.com/modelcontextprotocol/python-sdk/pulse
Code https://github.com/modelcontextprotocol/python-sdk
Issues https://github.com/modelcontextprotocol/python-sdk/issues
Pull requests https://github.com/modelcontextprotocol/python-sdk/pulls
Actions https://github.com/modelcontextprotocol/python-sdk/actions
Projects https://github.com/modelcontextprotocol/python-sdk/projects
Models https://github.com/modelcontextprotocol/python-sdk/models
Security and quality https://github.com/modelcontextprotocol/python-sdk/security
Insights https://github.com/modelcontextprotocol/python-sdk/pulse
Sign up for GitHub https://github.com/signup?return_to=%2Fmodelcontextprotocol%2Fpython-sdk%2Fissues%2Fnew%2Fchoose
terms of servicehttps://docs.github.com/terms
privacy statementhttps://docs.github.com/privacy
Sign inhttps://github.com/login?return_to=%2Fmodelcontextprotocol%2Fpython-sdk%2Fissues%2Fnew%2Fchoose
maxisbeyhttps://github.com/maxisbey
mainhttps://github.com/modelcontextprotocol/python-sdk/tree/main
maxisbey/deflake-stdio-testshttps://github.com/modelcontextprotocol/python-sdk/tree/maxisbey/deflake-stdio-tests
Conversation 8 https://github.com/modelcontextprotocol/python-sdk/pull/2773
Commits 16 https://github.com/modelcontextprotocol/python-sdk/pull/2773/commits
Checks 33 https://github.com/modelcontextprotocol/python-sdk/pull/2773/checks
Files changed https://github.com/modelcontextprotocol/python-sdk/pull/2773/files
Please reload this pagehttps://github.com/modelcontextprotocol/python-sdk/pull/2773/files
Fix stdio client shutdown bugs and rebuild the stdio test suite https://github.com/modelcontextprotocol/python-sdk/pull/2773/files#top
Show all changes 16 commits https://github.com/modelcontextprotocol/python-sdk/pull/2773/files
8a6abc0 Replace wall-clock margins in stdio cleanup tests with kernel-level s… maxisbey Jun 3, 2026 https://github.com/modelcontextprotocol/python-sdk/pull/2773/commits/8a6abc02a0b846f02996004f7ca955e77e302108
023300c Fix stdio client shutdown: cancellation deadlock, orphaned children, … maxisbey Jun 3, 2026 https://github.com/modelcontextprotocol/python-sdk/pull/2773/commits/023300caf540615aee0f054e666e18d7eba00820
3035984 Consolidate stdio tests: in-process logic tests, minimal real-process… maxisbey Jun 3, 2026 https://github.com/modelcontextprotocol/python-sdk/pull/2773/commits/3035984afcbb699c35f3606947cb2780ba1acdb5
fb960d9 Add real-subprocess stdio lifecycle tests for POSIX and Windows maxisbey Jun 4, 2026 https://github.com/modelcontextprotocol/python-sdk/pull/2773/commits/fb960d9e80d90d6631a09d0967eac01b6990b619
6b7fa82 Address review findings: comment accuracy, test hardening, trio reap pin maxisbey Jun 4, 2026 https://github.com/modelcontextprotocol/python-sdk/pull/2773/commits/6b7fa829d4c524288f9ebf1329e18839235bbc05
c5eff45 Make the Windows job-reap test diagnosable and align its server shape maxisbey Jun 4, 2026 https://github.com/modelcontextprotocol/python-sdk/pull/2773/commits/c5eff45b7728363b71a010f79983f58c6b1fd41a
2223efd Instrument the Windows job-reap test's child-side failures maxisbey Jun 4, 2026 https://github.com/modelcontextprotocol/python-sdk/pull/2773/commits/2223efd9497e0c72c6fed74e617f9d4f7aa60c52
1dc0f35 Spawn the job-reap test's grandchild via the base interpreter maxisbey Jun 4, 2026 https://github.com/modelcontextprotocol/python-sdk/pull/2773/commits/1dc0f3538f281cd32869412d5d56e88e1e029697
dbb885b Decouple the job-reap test's child from the server's stdin pipe maxisbey Jun 4, 2026 https://github.com/modelcontextprotocol/python-sdk/pull/2773/commits/dbb885b7af11ea6a1fe4c4319af95cffbe77704d
17a9dca Give the stdio interaction test's child headroom for coverage shutdown maxisbey Jun 4, 2026 https://github.com/modelcontextprotocol/python-sdk/pull/2773/commits/17a9dcac9a4b20fde3ea0c3ce84fdf5782a9833b
1ba4065 Simplify the stdio client transport maxisbey Jun 4, 2026 https://github.com/modelcontextprotocol/python-sdk/pull/2773/commits/1ba4065f59f5d5612d9db0a30cd0f24106143329
58f5a69 Fix stdio shutdown edge cases found in review maxisbey Jun 5, 2026 https://github.com/modelcontextprotocol/python-sdk/pull/2773/commits/58f5a695b0c0bc26684b37edc4f753deb1457a67
b7c2809 Simplify stdio client shutdown internals maxisbey Jun 5, 2026 https://github.com/modelcontextprotocol/python-sdk/pull/2773/commits/b7c2809aca14254933597bbf3d242c18d68ac96b
0f2c132 Annotate stdio_client's return type with TransportStreams maxisbey Jun 5, 2026 https://github.com/modelcontextprotocol/python-sdk/pull/2773/commits/0f2c1325690ad052590044985db50b577867e030
7adb379 Slim comments and docstrings across the stdio surface maxisbey Jun 5, 2026 https://github.com/modelcontextprotocol/python-sdk/pull/2773/commits/7adb379471f96c4efd950b513134fabdeb178df3
3c13fc9 Conform stdio docstrings to Google style maxisbey Jun 5, 2026 https://github.com/modelcontextprotocol/python-sdk/pull/2773/commits/3c13fc95ddbdaee00a6ad201efd5374ee01d3673
Clear filters https://github.com/modelcontextprotocol/python-sdk/pull/2773/files
Please reload this pagehttps://github.com/modelcontextprotocol/python-sdk/pull/2773/files
Please reload this pagehttps://github.com/modelcontextprotocol/python-sdk/pull/2773/files
migration.md https://github.com/modelcontextprotocol/python-sdk/pull/2773/files#diff-758ba107a728fccfdf0d098b2c06ded59127dd53ea287d630f72fb51040bc72d
stdio.py https://github.com/modelcontextprotocol/python-sdk/pull/2773/files#diff-a906fce75e115cde24e79b8cdac6442af7845748f57ec0e997ff81f089408186
utilities.py https://github.com/modelcontextprotocol/python-sdk/pull/2773/files#diff-c311b33a6b6ca2f6c5c9f1ec44fbfc336d4d7f6a5e7c69b9bf579b60df18b702
utilities.py https://github.com/modelcontextprotocol/python-sdk/pull/2773/files#diff-0adc630bbecb11fd2fe8fc302a21e9afe0ebb9c3ae019a95d9bf84817cf73f61
test_stdio.py https://github.com/modelcontextprotocol/python-sdk/pull/2773/files#diff-49f66b09e4d89b29b440c955c429fe948dbcc3bbb08fffb504cf40be24382352
test_stdio.py https://github.com/modelcontextprotocol/python-sdk/pull/2773/files#diff-e87dd7470dc7d367b9901aacfcc577a54864d05e8e50b4b9a25c6d1bfc543fb5
test_1027_win_unreachable_cleanup.py https://github.com/modelcontextprotocol/python-sdk/pull/2773/files#diff-58ee556cdf4f7669f21584c546737c09da73fcbb6b3b839a8db7212793152ff6
test_552_windows_hang.py https://github.com/modelcontextprotocol/python-sdk/pull/2773/files#diff-75f0c3f56e683e126a1427b31c4c5c2745e19a517433a65dbda20eff519564f4
test_elicitation.py https://github.com/modelcontextprotocol/python-sdk/pull/2773/files#diff-6cf9570e46bbc0eb2485392dfaa05780418f6295efc86d9f79bf047584880d54
test_stdio.py https://github.com/modelcontextprotocol/python-sdk/pull/2773/files#diff-3e62be39a5c1d8b8dfe922d017c0fae7b023fa1ffac872a0e046f13ef8ca899a
test_win32_utils.py https://github.com/modelcontextprotocol/python-sdk/pull/2773/files#diff-d9cfdc4b179126e0de08eeeb163c38dedf1359893920622a3f7c4d5f3e829a7b
__init__.py https://github.com/modelcontextprotocol/python-sdk/pull/2773/files#diff-343206963a75647fdc70efab86abe45a78eaccca0883c8568b331a8fc19c3889
__init__.py https://github.com/modelcontextprotocol/python-sdk/pull/2773/files#diff-12c99efd704599760cb1a5bcf2ae08331247ca826f4880892cd99af8eae86509
_liveness.py https://github.com/modelcontextprotocol/python-sdk/pull/2773/files#diff-8e3d803b95eb308e48896c12a56c4538d3f7e3d47479cc22994a71ce08965ec8
conftest.py https://github.com/modelcontextprotocol/python-sdk/pull/2773/files#diff-7ea490b371122c7bee3ef08f22f959735f2bac1d5240dfd382cafcc52159b3d5
test_lifecycle.py https://github.com/modelcontextprotocol/python-sdk/pull/2773/files#diff-dfe48f06b0fabf3d8171942bed96fe7a26a5557f860b742b9bd5cb4bb9d006b5
test_posix.py https://github.com/modelcontextprotocol/python-sdk/pull/2773/files#diff-499184b52f50cccda608f63c7f11cedee0fac7032fc1596711a908472f8386bf
test_windows.py https://github.com/modelcontextprotocol/python-sdk/pull/2773/files#diff-314c849a12297cace60d12dc9f5983e06fac171fdb2a7ed454a389c4e08aebb1
docs/migration.mdhttps://github.com/modelcontextprotocol/python-sdk/pull/2773/files#diff-758ba107a728fccfdf0d098b2c06ded59127dd53ea287d630f72fb51040bc72d
View file https://github.com/modelcontextprotocol/python-sdk/blob/3c13fc95ddbdaee00a6ad201efd5374ee01d3673/docs/migration.md
Open in desktop https://desktop.github.com
https://github.co/hiddenchars
https://github.com/modelcontextprotocol/python-sdk/pull/2773/{{ revealButtonHref }}
https://github.com/modelcontextprotocol/python-sdk/pull/2773/files#diff-758ba107a728fccfdf0d098b2c06ded59127dd53ea287d630f72fb51040bc72d
https://github.com/modelcontextprotocol/python-sdk/pull/2773/files#diff-758ba107a728fccfdf0d098b2c06ded59127dd53ea287d630f72fb51040bc72d
Please reload this pagehttps://github.com/modelcontextprotocol/python-sdk/pull/2773/files
Please reload this pagehttps://github.com/modelcontextprotocol/python-sdk/pull/2773/files
https://github.com
Termshttps://docs.github.com/site-policy/github-terms/github-terms-of-service
Privacyhttps://docs.github.com/site-policy/privacy-policies/github-privacy-statement
Securityhttps://github.com/security
Statushttps://www.githubstatus.com/
Communityhttps://github.community/
Docshttps://docs.github.com/
Contacthttps://support.github.com?tags=dotcom-footer

Viewport: width=device-width


URLs of crawlers that visited me.