From b29c06b20ef28282f030b0bce50c202452441e96 Mon Sep 17 00:00:00 2001 From: Stephen Halter Date: Wed, 9 Apr 2025 09:47:15 -0700 Subject: [PATCH 1/2] Fix race in TransportBase.SetConnected - Previously the ChannelWriter could already be completed if multiple threads raced in SetConnected(false) --- .../Protocol/Transport/TransportBase.cs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/ModelContextProtocol/Protocol/Transport/TransportBase.cs b/src/ModelContextProtocol/Protocol/Transport/TransportBase.cs index 75a9a9b5f..7ea14494c 100644 --- a/src/ModelContextProtocol/Protocol/Transport/TransportBase.cs +++ b/src/ModelContextProtocol/Protocol/Transport/TransportBase.cs @@ -13,7 +13,7 @@ public abstract class TransportBase : ITransport { private readonly Channel _messageChannel; private readonly ILogger _logger; - private bool _isConnected; + private int _isConnected; /// /// Initializes a new instance of the class. @@ -30,7 +30,7 @@ protected TransportBase(ILoggerFactory? loggerFactory) } /// - public bool IsConnected => _isConnected; + public bool IsConnected => _isConnected == 1; /// public ChannelReader MessageReader => _messageChannel.Reader; @@ -48,7 +48,7 @@ protected TransportBase(ILoggerFactory? loggerFactory) /// The to monitor for cancellation requests. The default is . protected async Task WriteMessageAsync(IJsonRpcMessage message, CancellationToken cancellationToken = default) { - if (!_isConnected) + if (IsConnected) { throw new McpTransportException("Transport is not connected"); } @@ -64,12 +64,12 @@ protected async Task WriteMessageAsync(IJsonRpcMessage message, CancellationToke /// Whether the transport is connected. protected void SetConnected(bool isConnected) { - if (_isConnected == isConnected) + var newIsConnected = isConnected ? 1 : 0; + if (Interlocked.Exchange(ref _isConnected, newIsConnected) == newIsConnected) { return; } - _isConnected = isConnected; if (!isConnected) { _messageChannel.Writer.Complete(); From 27f88b9e7ac7708525596fed4f7663badafda871 Mon Sep 17 00:00:00 2001 From: Stephen Halter Date: Wed, 9 Apr 2025 09:58:15 -0700 Subject: [PATCH 2/2] Fix WriteMessageAsync IsConnected test --- src/ModelContextProtocol/Protocol/Transport/TransportBase.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ModelContextProtocol/Protocol/Transport/TransportBase.cs b/src/ModelContextProtocol/Protocol/Transport/TransportBase.cs index 7ea14494c..da499c8a6 100644 --- a/src/ModelContextProtocol/Protocol/Transport/TransportBase.cs +++ b/src/ModelContextProtocol/Protocol/Transport/TransportBase.cs @@ -48,7 +48,7 @@ protected TransportBase(ILoggerFactory? loggerFactory) /// The to monitor for cancellation requests. The default is . protected async Task WriteMessageAsync(IJsonRpcMessage message, CancellationToken cancellationToken = default) { - if (IsConnected) + if (!IsConnected) { throw new McpTransportException("Transport is not connected"); }