Skip to content

Commit 5546645

Browse files
committed
Add back dispose lock
1 parent 464d3f6 commit 5546645

File tree

3 files changed

+15
-4
lines changed

3 files changed

+15
-4
lines changed

src/ModelContextProtocol.Core/Client/McpClientImpl.cs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
using Microsoft.Extensions.Logging;
22
using Microsoft.Extensions.Logging.Abstractions;
33
using ModelContextProtocol.Protocol;
4+
using System.Runtime.InteropServices;
45
using System.Text.Json;
56

67
namespace ModelContextProtocol.Client;
@@ -19,14 +20,15 @@ internal sealed partial class McpClientImpl : McpClient
1920
private readonly string _endpointName;
2021
private readonly McpClientOptions _options;
2122
private readonly McpSessionHandler _sessionHandler;
23+
private readonly SemaphoreSlim _disposeLock = new(1, 1);
2224

2325
private CancellationTokenSource? _connectCts;
2426

2527
private ServerCapabilities? _serverCapabilities;
2628
private Implementation? _serverInfo;
2729
private string? _serverInstructions;
2830

29-
private int _isDisposed;
31+
private bool _disposed;
3032

3133
/// <summary>
3234
/// Initializes a new instance of the <see cref="McpClientImpl"/> class.
@@ -215,11 +217,15 @@ public override IAsyncDisposable RegisterNotificationHandler(string method, Func
215217
/// <inheritdoc/>
216218
public override async ValueTask DisposeAsync()
217219
{
218-
if (Interlocked.CompareExchange(ref _isDisposed, 1, 0) != 0)
220+
using var _ = await _disposeLock.LockAsync().ConfigureAwait(false);
221+
222+
if (_disposed)
219223
{
220224
return;
221225
}
222226

227+
_disposed = true;
228+
223229
await _sessionHandler.DisposeAsync().ConfigureAwait(false);
224230
await _transport.DisposeAsync().ConfigureAwait(false);
225231
}

src/ModelContextProtocol.Core/Server/McpServerImpl.cs

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ internal sealed class McpServerImpl : McpServer
2323
private readonly NotificationHandlers _notificationHandlers;
2424
private readonly RequestHandlers _requestHandlers;
2525
private readonly McpSessionHandler _sessionHandler;
26+
private readonly SemaphoreSlim _disposeLock = new(1, 1);
2627

2728
private ClientCapabilities? _clientCapabilities;
2829
private Implementation? _clientInfo;
@@ -31,7 +32,7 @@ internal sealed class McpServerImpl : McpServer
3132
private string _endpointName;
3233
private int _started;
3334

34-
private int _isDisposed;
35+
private bool _disposed;
3536

3637
/// <summary>Holds a boxed <see cref="LoggingLevel"/> value for the server.</summary>
3738
/// <remarks>
@@ -165,11 +166,15 @@ public override IAsyncDisposable RegisterNotificationHandler(string method, Func
165166
/// <inheritdoc/>
166167
public override async ValueTask DisposeAsync()
167168
{
168-
if (Interlocked.CompareExchange(ref _isDisposed, 1, 0) != 0)
169+
using var _ = await _disposeLock.LockAsync().ConfigureAwait(false);
170+
171+
if (_disposed)
169172
{
170173
return;
171174
}
172175

176+
_disposed = true;
177+
173178
_disposables.ForEach(d => d());
174179
await _sessionHandler.DisposeAsync().ConfigureAwait(false);
175180
}

tests/ModelContextProtocol.Tests/Client/McpClientExtensionsTest.cs renamed to tests/ModelContextProtocol.Tests/Client/McpClientExtensionsTests.cs

File renamed without changes.

0 commit comments

Comments
 (0)