static void Shutdown(ServiceHubRemoteHostClient client, Exception ex, CancellationToken cancellationToken) { // make sure we shutdown client if initializing client has failed. client?.Shutdown(); // translate to our own cancellation if it is raised. cancellationToken.ThrowIfCancellationRequested(); // otherwise, report watson ex.ReportServiceHubNFW("ServiceHub creation failed"); }
public static async Task <ServiceHubRemoteHostClient> CreateWorkerAsync(Workspace workspace, HubClient primary, TimeSpan timeout, CancellationToken cancellationToken) { ServiceHubRemoteHostClient client = null; try { // let each client to have unique id so that we can distinguish different clients when service is restarted var currentInstanceId = Interlocked.Add(ref s_instanceId, 1); var current = $"VS ({Process.GetCurrentProcess().Id}) ({currentInstanceId})"; var hostGroup = new HostGroup(current); var remoteHostStream = await Connections.RequestServiceAsync(workspace, primary, WellKnownRemoteHostServices.RemoteHostService, hostGroup, timeout, cancellationToken).ConfigureAwait(false); var remotableDataRpc = new RemotableDataJsonRpc( workspace, primary.Logger, await Connections.RequestServiceAsync(workspace, primary, WellKnownServiceHubServices.SnapshotService, hostGroup, timeout, cancellationToken).ConfigureAwait(false)); var enableConnectionPool = workspace.Options.GetOption(RemoteHostOptions.EnableConnectionPool); var maxConnection = workspace.Options.GetOption(RemoteHostOptions.MaxPoolConnection); var connectionManager = new ConnectionManager(primary, hostGroup, enableConnectionPool, maxConnection, timeout, new ReferenceCountedDisposable <RemotableDataJsonRpc>(remotableDataRpc)); client = new ServiceHubRemoteHostClient(workspace, connectionManager, remoteHostStream); var uiCultureLCID = CultureInfo.CurrentUICulture.LCID; var cultureLCID = CultureInfo.CurrentCulture.LCID; // make sure connection is done right var host = await client._rpc.InvokeWithCancellationAsync <string>( nameof(IRemoteHostService.Connect), new object[] { current, uiCultureLCID, cultureLCID, TelemetryService.DefaultSession.SerializeSettings() }, cancellationToken).ConfigureAwait(false); return(client); } catch (Exception ex) { // make sure we shutdown client if initializing client has failed. client?.Shutdown(); // translate to our own cancellation if it is raised. cancellationToken.ThrowIfCancellationRequested(); // otherwise, report watson and throw original exception ex.ReportServiceHubNFW("ServiceHub creation failed"); throw; } }
public static async Task <RemoteHostClient?> CreateAsync(Workspace workspace, CancellationToken cancellationToken) { using (Logger.LogBlock(FunctionId.ServiceHubRemoteHostClient_CreateAsync, cancellationToken)) { var timeout = TimeSpan.FromMilliseconds(workspace.Options.GetOption(RemoteHostOptions.RequestServiceTimeoutInMS)); var enableConnectionPool = workspace.Options.GetOption(RemoteHostOptions.EnableConnectionPool); var maxConnection = workspace.Options.GetOption(RemoteHostOptions.MaxPoolConnection); // let each client to have unique id so that we can distinguish different clients when service is restarted var clientId = CreateClientId(Process.GetCurrentProcess().Id.ToString()); var hostGroup = new HostGroup(clientId); var primary = new HubClient("ManagedLanguage.IDE.RemoteHostClient"); ServiceHubRemoteHostClient?client = null; try { // Create the RemotableDataJsonRpc before we create the remote host: this call implicitly sets up the remote IExperimentationService so that will be available for later calls var snapshotServiceStream = await Connections.RequestServiceAsync(workspace, primary, WellKnownServiceHubServices.SnapshotService, hostGroup, timeout, cancellationToken).ConfigureAwait(false); var remoteHostStream = await Connections.RequestServiceAsync(workspace, primary, WellKnownRemoteHostServices.RemoteHostService, hostGroup, timeout, cancellationToken).ConfigureAwait(false); var remotableDataRpc = new RemotableDataJsonRpc(workspace, primary.Logger, snapshotServiceStream); var connectionManager = new ConnectionManager(primary, hostGroup, enableConnectionPool, maxConnection, timeout, new ReferenceCountedDisposable <RemotableDataJsonRpc>(remotableDataRpc)); client = new ServiceHubRemoteHostClient(workspace, primary.Logger, connectionManager, remoteHostStream); var uiCultureLCID = CultureInfo.CurrentUICulture.LCID; var cultureLCID = CultureInfo.CurrentCulture.LCID; // make sure connection is done right var host = await client._rpc.InvokeWithCancellationAsync <string>( nameof(IRemoteHostService.Connect), new object[] { clientId, uiCultureLCID, cultureLCID, TelemetryService.DefaultSession.SerializeSettings() }, cancellationToken).ConfigureAwait(false); client.Started(); return(client); } catch (ConnectionLostException ex) { RemoteHostCrashInfoBar.ShowInfoBar(workspace, ex); Shutdown(ex); // dont crash VS because OOP is failed to start. we will show info bar telling users to restart // but never physically crash VS. return(null); } catch (SoftCrashException ex) { Shutdown(ex); // at this point, we should have shown info bar (RemoteHostCrashInfoBar.ShowInfoBar) to users // returning null here will disable OOP for this VS session. // * Note * this is not trying to recover the exception. but giving users to time // to clean up before restart VS return(null); } catch (Exception ex) { Shutdown(ex); throw; } void Shutdown(Exception ex) { // make sure we shutdown client if initializing client has failed. client?.Shutdown(); // translate to our own cancellation if it is raised. cancellationToken.ThrowIfCancellationRequested(); // otherwise, report watson ex.ReportServiceHubNFW("ServiceHub creation failed"); } } }