From f556505b0b5f6a76ec07cee8b60a9abc78d0ca79 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 2 Mar 2026 13:35:23 +0000 Subject: [PATCH 1/2] Initial plan From d555dc62ebc2f81f8158e0693039ec6af0b522a1 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 2 Mar 2026 13:48:38 +0000 Subject: [PATCH 2/2] Remove unnecessary SemaphoreSlims for _permissionHandlerLock and _userInputHandlerLock Replace SemaphoreSlim-based locking with volatile fields for _permissionHandler and _userInputHandler. These fields are single reference types where reads and writes are atomic in .NET, so locking is unnecessary. The volatile keyword ensures proper visibility across threads. Co-authored-by: stephentoub <2642209+stephentoub@users.noreply.github.com> --- dotnet/src/Session.cs | 58 ++++++------------------------------------- 1 file changed, 7 insertions(+), 51 deletions(-) diff --git a/dotnet/src/Session.cs b/dotnet/src/Session.cs index 923b193cc..e749742f6 100644 --- a/dotnet/src/Session.cs +++ b/dotnet/src/Session.cs @@ -47,10 +47,8 @@ public partial class CopilotSession : IAsyncDisposable private readonly HashSet _eventHandlers = new(); private readonly Dictionary _toolHandlers = new(); private readonly JsonRpc _rpc; - private PermissionRequestHandler? _permissionHandler; - private readonly SemaphoreSlim _permissionHandlerLock = new(1, 1); - private UserInputHandler? _userInputHandler; - private readonly SemaphoreSlim _userInputHandlerLock = new(1, 1); + private volatile PermissionRequestHandler? _permissionHandler; + private volatile UserInputHandler? _userInputHandler; private SessionHooks? _hooks; private readonly SemaphoreSlim _hooksLock = new(1, 1); private SessionRpc? _sessionRpc; @@ -300,15 +298,7 @@ internal void RegisterTools(ICollection tools) /// internal void RegisterPermissionHandler(PermissionRequestHandler handler) { - _permissionHandlerLock.Wait(); - try - { - _permissionHandler = handler; - } - finally - { - _permissionHandlerLock.Release(); - } + _permissionHandler = handler; } /// @@ -318,16 +308,7 @@ internal void RegisterPermissionHandler(PermissionRequestHandler handler) /// A task that resolves with the permission decision. internal async Task HandlePermissionRequestAsync(JsonElement permissionRequestData) { - await _permissionHandlerLock.WaitAsync(); - PermissionRequestHandler? handler; - try - { - handler = _permissionHandler; - } - finally - { - _permissionHandlerLock.Release(); - } + var handler = _permissionHandler; if (handler == null) { @@ -354,15 +335,7 @@ internal async Task HandlePermissionRequestAsync(JsonEl /// The handler to invoke when user input is requested. internal void RegisterUserInputHandler(UserInputHandler handler) { - _userInputHandlerLock.Wait(); - try - { - _userInputHandler = handler; - } - finally - { - _userInputHandlerLock.Release(); - } + _userInputHandler = handler; } /// @@ -372,16 +345,7 @@ internal void RegisterUserInputHandler(UserInputHandler handler) /// A task that resolves with the user's response. internal async Task HandleUserInputRequestAsync(UserInputRequest request) { - await _userInputHandlerLock.WaitAsync(); - UserInputHandler? handler; - try - { - handler = _userInputHandler; - } - finally - { - _userInputHandlerLock.Release(); - } + var handler = _userInputHandler; if (handler == null) { @@ -589,15 +553,7 @@ await InvokeRpcAsync( _eventHandlers.Clear(); _toolHandlers.Clear(); - await _permissionHandlerLock.WaitAsync(); - try - { - _permissionHandler = null; - } - finally - { - _permissionHandlerLock.Release(); - } + _permissionHandler = null; } private class OnDisposeCall(Action callback) : IDisposable