Skip to content

Close streams outside mutex in session cleanup#291

Merged
koic merged 1 commit intomodelcontextprotocol:mainfrom
koic:improvement_close_streams_outside_mutex
Apr 3, 2026
Merged

Close streams outside mutex in session cleanup#291
koic merged 1 commit intomodelcontextprotocol:mainfrom
koic:improvement_close_streams_outside_mutex

Conversation

@koic
Copy link
Copy Markdown
Member

@koic koic commented Apr 3, 2026

Motivation and Context

cleanup_session_unsafe was closing streams inside the mutex, which could block all session operations if stream.close is slow or blocks (e.g., waiting for network I/O). The original reap_expired_sessions avoided this by closing streams outside the mutex, but the other 6 call sites of cleanup_session_unsafe did not, creating an inconsistency.

This change separates stream closing from session deletion. cleanup_session_unsafe now only removes the session from @sessions and returns it. All callers close streams outside the mutex via close_stream_safely, ensuring consistent behavior and preventing mutex contention from blocking I/O.

How Has This Been Tested?

Added tests that verify streams are closed outside the mutex by using Mutex#try_lock inside mock stream close callbacks:

  • reap_expired_sessions closes stream outside mutex
  • send_notification closes stream outside mutex on write error

Breaking Changes

None. This is an internal improvement with no change to public API behavior.

Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)
  • Documentation update

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

## Motivation and Context

`cleanup_session_unsafe` was closing streams inside the mutex, which could block all session
operations if `stream.close` is slow or blocks (e.g., waiting for network I/O).
The original `reap_expired_sessions` avoided this by closing streams outside the mutex,
but the other 6 call sites of `cleanup_session_unsafe` did not, creating an inconsistency.

This change separates stream closing from session deletion. `cleanup_session_unsafe`
now only removes the session from `@sessions` and returns it.
All callers close streams outside the mutex via `close_stream_safely`,
ensuring consistent behavior and preventing mutex contention from blocking I/O.

## How Has This Been Tested?

Added tests that verify streams are closed outside the mutex by using `Mutex#try_lock`
inside mock stream close callbacks:

- `reap_expired_sessions closes stream outside mutex`
- `send_notification closes stream outside mutex on write error`

## Breaking Changes

None. This is an internal improvement with no change to public API behavior.
@koic koic merged commit 5285277 into modelcontextprotocol:main Apr 3, 2026
11 checks passed
@koic koic deleted the improvement_close_streams_outside_mutex branch April 3, 2026 20:50
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.

2 participants