diff --git a/src/Workspaces/Remote/Core/RemoteCallback.cs b/src/Workspaces/Remote/Core/RemoteCallback.cs index aa3d1d3402437..089d312b3fdd5 100644 --- a/src/Workspaces/Remote/Core/RemoteCallback.cs +++ b/src/Workspaces/Remote/Core/RemoteCallback.cs @@ -9,10 +9,7 @@ using System.IO.Pipelines; using System.Threading; using System.Threading.Tasks; -using MessagePack; using Microsoft.CodeAnalysis.ErrorReporting; -using Nerdbank.Streams; -using Newtonsoft.Json; using Roslyn.Utilities; using StreamJsonRpc; @@ -30,12 +27,9 @@ internal readonly struct RemoteCallback { private readonly T _callback; - public readonly CancellationTokenSource ClientDisconnectedSource; - - public RemoteCallback(T callback, CancellationTokenSource clientDisconnectedSource) + public RemoteCallback(T callback) { _callback = callback; - ClientDisconnectedSource = clientDisconnectedSource; } public async ValueTask InvokeAsync(Func invocation, CancellationToken cancellationToken) @@ -46,7 +40,7 @@ public async ValueTask InvokeAsync(Func invocat } catch (Exception exception) when (ReportUnexpectedException(exception, cancellationToken)) { - throw OnUnexpectedException(cancellationToken); + throw OnUnexpectedException(exception, cancellationToken); } } @@ -58,7 +52,7 @@ public async ValueTask InvokeAsync(Func InvokeAsync( } catch (Exception exception) when (ReportUnexpectedException(exception, cancellationToken)) { - throw OnUnexpectedException(cancellationToken); + throw OnUnexpectedException(exception, cancellationToken); } } @@ -87,7 +81,7 @@ public async ValueTask InvokeAsync( // 3) Remote exception - an exception was thrown by the callee // 4) Cancelation // - private bool ReportUnexpectedException(Exception exception, CancellationToken cancellationToken) + private static bool ReportUnexpectedException(Exception exception, CancellationToken cancellationToken) { if (exception is IOException) { @@ -114,8 +108,6 @@ private bool ReportUnexpectedException(Exception exception, CancellationToken ca // as any observation of ConnectionLostException indicates a bug (e.g. https://github.com/microsoft/vs-streamjsonrpc/issues/549). if (exception is ConnectionLostException) { - ClientDisconnectedSource.Cancel(); - return true; } @@ -123,11 +115,17 @@ private bool ReportUnexpectedException(Exception exception, CancellationToken ca return FatalError.ReportWithoutCrashAndPropagate(exception); } - private static Exception OnUnexpectedException(CancellationToken cancellationToken) + private static Exception OnUnexpectedException(Exception exception, CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); - // If this is hit the cancellation token passed to the service implementation did not use the correct token. + if (exception is ConnectionLostException) + { + throw new OperationCanceledException(exception.Message, exception); + } + + // If this is hit the cancellation token passed to the service implementation did not use the correct token, + // and the resulting exception was not a ConnectionLostException. return ExceptionUtilities.Unreachable; } } diff --git a/src/Workspaces/Remote/ServiceHub/Host/SolutionAssetSource.cs b/src/Workspaces/Remote/ServiceHub/Host/SolutionAssetSource.cs index b1b198df49fa9..7ad7c7e8d7284 100644 --- a/src/Workspaces/Remote/ServiceHub/Host/SolutionAssetSource.cs +++ b/src/Workspaces/Remote/ServiceHub/Host/SolutionAssetSource.cs @@ -19,12 +19,10 @@ namespace Microsoft.CodeAnalysis.Remote internal sealed class SolutionAssetSource : IAssetSource { private readonly ServiceBrokerClient _client; - private readonly CancellationTokenSource _clientDisconnectedSource; - public SolutionAssetSource(ServiceBrokerClient client, CancellationTokenSource clientDisconnectedSource) + public SolutionAssetSource(ServiceBrokerClient client) { _client = client; - _clientDisconnectedSource = clientDisconnectedSource; } public async ValueTask> GetAssetsAsync(int scopeId, ISet checksums, ISerializerService serializerService, CancellationToken cancellationToken) @@ -35,7 +33,7 @@ public SolutionAssetSource(ServiceBrokerClient client, CancellationTokenSource c using var provider = await _client.GetProxyAsync(SolutionAssetProvider.ServiceDescriptor, cancellationToken).ConfigureAwait(false); Contract.ThrowIfNull(provider.Proxy); - return await new RemoteCallback(provider.Proxy, _clientDisconnectedSource).InvokeAsync( + return await new RemoteCallback(provider.Proxy).InvokeAsync( (proxy, pipeWriter, cancellationToken) => proxy.GetAssetsAsync(pipeWriter, scopeId, checksums.ToArray(), cancellationToken), (pipeReader, cancellationToken) => RemoteHostAssetSerialization.ReadDataAsync(pipeReader, scopeId, checksums, serializerService, cancellationToken), cancellationToken).ConfigureAwait(false); @@ -49,7 +47,7 @@ public async ValueTask IsExperimentEnabledAsync(string experimentName, Can using var provider = await _client.GetProxyAsync(SolutionAssetProvider.ServiceDescriptor, cancellationToken).ConfigureAwait(false); Contract.ThrowIfNull(provider.Proxy); - return await new RemoteCallback(provider.Proxy, _clientDisconnectedSource).InvokeAsync( + return await new RemoteCallback(provider.Proxy).InvokeAsync( (self, cancellationToken) => provider.Proxy.IsExperimentEnabledAsync(experimentName, cancellationToken), cancellationToken).ConfigureAwait(false); } diff --git a/src/Workspaces/Remote/ServiceHub/Services/BrokeredServiceBase.FactoryBase.cs b/src/Workspaces/Remote/ServiceHub/Services/BrokeredServiceBase.FactoryBase.cs index 4841903ec58a3..429f4a2ebe2d0 100644 --- a/src/Workspaces/Remote/ServiceHub/Services/BrokeredServiceBase.FactoryBase.cs +++ b/src/Workspaces/Remote/ServiceHub/Services/BrokeredServiceBase.FactoryBase.cs @@ -8,7 +8,6 @@ using System.Diagnostics; using System.IO; using System.IO.Pipelines; -using System.Threading; using System.Threading.Tasks; using Microsoft.ServiceHub.Framework; using Microsoft.ServiceHub.Framework.Services; @@ -74,7 +73,7 @@ internal TService Create( var serviceHubTraceSource = (TraceSource)hostProvidedServices.GetService(typeof(TraceSource)); var serverConnection = descriptor.WithTraceSource(serviceHubTraceSource).ConstructRpcConnection(pipe); - var args = new ServiceConstructionArguments(hostProvidedServices, serviceBroker, new CancellationTokenSource()); + var args = new ServiceConstructionArguments(hostProvidedServices, serviceBroker); var service = CreateService(args, descriptor, serverConnection, serviceActivationOptions.ClientRpcTarget); serverConnection.AddLocalRpcTarget(service); @@ -106,7 +105,7 @@ protected sealed override TService CreateService( { Contract.ThrowIfNull(descriptor.ClientInterface); var callback = (TCallback)(clientRpcTarget ?? serverConnection.ConstructRpcClient(descriptor.ClientInterface)); - return CreateService(arguments, new RemoteCallback(callback, arguments.ClientDisconnectedSource)); + return CreateService(arguments, new RemoteCallback(callback)); } } } diff --git a/src/Workspaces/Remote/ServiceHub/Services/BrokeredServiceBase.ServiceConstructionArguments.cs b/src/Workspaces/Remote/ServiceHub/Services/BrokeredServiceBase.ServiceConstructionArguments.cs index 3569393b81742..43eab4ac84356 100644 --- a/src/Workspaces/Remote/ServiceHub/Services/BrokeredServiceBase.ServiceConstructionArguments.cs +++ b/src/Workspaces/Remote/ServiceHub/Services/BrokeredServiceBase.ServiceConstructionArguments.cs @@ -5,7 +5,6 @@ #nullable enable using System; -using System.Threading; using Microsoft.ServiceHub.Framework; namespace Microsoft.CodeAnalysis.Remote @@ -16,13 +15,11 @@ internal readonly struct ServiceConstructionArguments { public readonly IServiceProvider ServiceProvider; public readonly IServiceBroker ServiceBroker; - public readonly CancellationTokenSource ClientDisconnectedSource; - public ServiceConstructionArguments(IServiceProvider serviceProvider, IServiceBroker serviceBroker, CancellationTokenSource clientDisconnectedSource) + public ServiceConstructionArguments(IServiceProvider serviceProvider, IServiceBroker serviceBroker) { ServiceProvider = serviceProvider; ServiceBroker = serviceBroker; - ClientDisconnectedSource = clientDisconnectedSource; } } } diff --git a/src/Workspaces/Remote/ServiceHub/Services/BrokeredServiceBase.cs b/src/Workspaces/Remote/ServiceHub/Services/BrokeredServiceBase.cs index dcbc5e4aeb99e..5ee6d4037c966 100644 --- a/src/Workspaces/Remote/ServiceHub/Services/BrokeredServiceBase.cs +++ b/src/Workspaces/Remote/ServiceHub/Services/BrokeredServiceBase.cs @@ -6,15 +6,10 @@ using System; using System.Diagnostics; -using System.IO; -using System.IO.Pipelines; using System.Threading; using System.Threading.Tasks; using Microsoft.CodeAnalysis.ErrorReporting; using Microsoft.ServiceHub.Framework; -using Microsoft.ServiceHub.Framework.Services; -using Microsoft.VisualStudio.Threading; -using Nerdbank.Streams; using Roslyn.Utilities; namespace Microsoft.CodeAnalysis.Remote @@ -28,7 +23,6 @@ internal abstract partial class BrokeredServiceBase : IDisposable protected readonly RemoteWorkspaceManager WorkspaceManager; protected readonly SolutionAssetSource SolutionAssetSource; - protected readonly CancellationTokenSource ClientDisconnectedSource; protected readonly ServiceBrokerClient ServiceBrokerClient; // test data are only available when running tests: @@ -49,8 +43,7 @@ protected BrokeredServiceBase(in ServiceConstructionArguments arguments) ServiceBrokerClient = new ServiceBrokerClient(arguments.ServiceBroker); #pragma warning restore - SolutionAssetSource = new SolutionAssetSource(ServiceBrokerClient, arguments.ClientDisconnectedSource); - ClientDisconnectedSource = arguments.ClientDisconnectedSource; + SolutionAssetSource = new SolutionAssetSource(ServiceBrokerClient); } public void Dispose() @@ -72,11 +65,10 @@ protected Task GetSolutionAsync(PinnedSolutionInfo solutionInfo, Cance protected async ValueTask RunServiceAsync(Func> implementation, CancellationToken cancellationToken) { WorkspaceManager.SolutionAssetCache.UpdateLastActivityTime(); - using var combined = cancellationToken.CombineWith(ClientDisconnectedSource.Token); try { - return await implementation(combined.Token).ConfigureAwait(false); + return await implementation(cancellationToken).ConfigureAwait(false); } catch (Exception ex) when (FatalError.ReportWithoutCrashUnlessCanceledAndPropagate(ex, cancellationToken)) { @@ -87,11 +79,10 @@ protected async ValueTask RunServiceAsync(Func implementation, CancellationToken cancellationToken) { WorkspaceManager.SolutionAssetCache.UpdateLastActivityTime(); - using var combined = cancellationToken.CombineWith(ClientDisconnectedSource.Token); try { - await implementation(combined.Token).ConfigureAwait(false); + await implementation(cancellationToken).ConfigureAwait(false); } catch (Exception ex) when (FatalError.ReportWithoutCrashUnlessCanceledAndPropagate(ex, cancellationToken)) { diff --git a/src/Workspaces/Remote/ServiceHub/Services/DesignerAttributeDiscovery/RemoteDesignerAttributeIncrementalAnalyzer.cs b/src/Workspaces/Remote/ServiceHub/Services/DesignerAttributeDiscovery/RemoteDesignerAttributeIncrementalAnalyzer.cs index 195418a5d442c..1d316962cbdd9 100644 --- a/src/Workspaces/Remote/ServiceHub/Services/DesignerAttributeDiscovery/RemoteDesignerAttributeIncrementalAnalyzer.cs +++ b/src/Workspaces/Remote/ServiceHub/Services/DesignerAttributeDiscovery/RemoteDesignerAttributeIncrementalAnalyzer.cs @@ -27,22 +27,16 @@ public RemoteDesignerAttributeIncrementalAnalyzer(Workspace workspace, RemoteCal protected override async ValueTask ReportProjectRemovedAsync(ProjectId projectId, CancellationToken cancellationToken) { - // cancel whenever the analyzer runner cancels or the client disconnects and the request is canceled: - using var linkedSource = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, _callback.ClientDisconnectedSource.Token); - await _callback.InvokeAsync( (callback, cancellationToken) => callback.OnProjectRemovedAsync(projectId, cancellationToken), - linkedSource.Token).ConfigureAwait(false); + cancellationToken).ConfigureAwait(false); } protected override async ValueTask ReportDesignerAttributeDataAsync(List data, CancellationToken cancellationToken) { - // cancel whenever the analyzer runner cancels or the client disconnects and the request is canceled: - using var linkedSource = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, _callback.ClientDisconnectedSource.Token); - await _callback.InvokeAsync( (callback, cancellationToken) => callback.ReportDesignerAttributeDataAsync(data.ToImmutableArray(), cancellationToken), - linkedSource.Token).ConfigureAwait(false); + cancellationToken).ConfigureAwait(false); } } } diff --git a/src/Workspaces/Remote/ServiceHub/Services/ProjectTelemetry/RemoteProjectTelemetryIncrementalAnalyzer.cs b/src/Workspaces/Remote/ServiceHub/Services/ProjectTelemetry/RemoteProjectTelemetryIncrementalAnalyzer.cs index b5a01c19f82d3..84a79aee04856 100644 --- a/src/Workspaces/Remote/ServiceHub/Services/ProjectTelemetry/RemoteProjectTelemetryIncrementalAnalyzer.cs +++ b/src/Workspaces/Remote/ServiceHub/Services/ProjectTelemetry/RemoteProjectTelemetryIncrementalAnalyzer.cs @@ -9,7 +9,6 @@ using System.Threading.Tasks; using Microsoft.CodeAnalysis.ProjectTelemetry; using Microsoft.CodeAnalysis.SolutionCrawler; -using StreamJsonRpc; namespace Microsoft.CodeAnalysis.Remote { @@ -67,12 +66,9 @@ public override async Task AnalyzeProjectAsync(Project project, bool semanticsCh _projectToData[projectId] = info; } - // cancel whenever the analyzer runner cancels or the client disconnects and the request is canceled: - using var linkedSource = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, _callback.ClientDisconnectedSource.Token); - await _callback.InvokeAsync( (callback, cancellationToken) => callback.ReportProjectTelemetryDataAsync(info, cancellationToken), - linkedSource.Token).ConfigureAwait(false); + cancellationToken).ConfigureAwait(false); } public override Task RemoveProjectAsync(ProjectId projectId, CancellationToken cancellationToken) diff --git a/src/Workspaces/Remote/ServiceHub/Services/TodoCommentsDiscovery/RemoteTodoCommentsIncrementalAnalyzer.cs b/src/Workspaces/Remote/ServiceHub/Services/TodoCommentsDiscovery/RemoteTodoCommentsIncrementalAnalyzer.cs index 9d44a17fe9832..b4e390d1dd20f 100644 --- a/src/Workspaces/Remote/ServiceHub/Services/TodoCommentsDiscovery/RemoteTodoCommentsIncrementalAnalyzer.cs +++ b/src/Workspaces/Remote/ServiceHub/Services/TodoCommentsDiscovery/RemoteTodoCommentsIncrementalAnalyzer.cs @@ -23,12 +23,9 @@ public RemoteTodoCommentsIncrementalAnalyzer(RemoteCallback data, CancellationToken cancellationToken) { - // cancel whenever the analyzer runner cancels or the client disconnects and the request is canceled: - using var linkedSource = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, _callback.ClientDisconnectedSource.Token); - await _callback.InvokeAsync( (callback, cancellationToken) => callback.ReportTodoCommentDataAsync(documentId, data, cancellationToken), - linkedSource.Token).ConfigureAwait(false); + cancellationToken).ConfigureAwait(false); } } }