未验证 提交 4bb1ffe5 编写于 作者: H Heejae Chang 提交者: GitHub

add ClientId to RemoteHost so that test window can discover our OOP from thier own OOP (#30333)

上级 c6b7941c
...@@ -29,10 +29,10 @@ public static async Task<RemoteHostClient> CreateAsync(Workspace workspace, bool ...@@ -29,10 +29,10 @@ public static async Task<RemoteHostClient> CreateAsync(Workspace workspace, bool
var remoteHostStream = await inprocServices.RequestServiceAsync(WellKnownRemoteHostServices.RemoteHostService, cancellationToken).ConfigureAwait(false); var remoteHostStream = await inprocServices.RequestServiceAsync(WellKnownRemoteHostServices.RemoteHostService, cancellationToken).ConfigureAwait(false);
var remotableDataRpc = new RemotableDataJsonRpc(workspace, inprocServices.Logger, await inprocServices.RequestServiceAsync(WellKnownServiceHubServices.SnapshotService, cancellationToken).ConfigureAwait(false)); var remotableDataRpc = new RemotableDataJsonRpc(workspace, inprocServices.Logger, await inprocServices.RequestServiceAsync(WellKnownServiceHubServices.SnapshotService, cancellationToken).ConfigureAwait(false));
var instance = new InProcRemoteHostClient(workspace, inprocServices, new ReferenceCountedDisposable<RemotableDataJsonRpc>(remotableDataRpc), remoteHostStream); var current = CreateClientId(Process.GetCurrentProcess().Id.ToString());
var instance = new InProcRemoteHostClient(current, workspace, inprocServices, new ReferenceCountedDisposable<RemotableDataJsonRpc>(remotableDataRpc), remoteHostStream);
// make sure connection is done right // make sure connection is done right
var current = $"VS ({Process.GetCurrentProcess().Id})";
var telemetrySession = default(string); var telemetrySession = default(string);
var uiCultureLCIDE = 0; var uiCultureLCIDE = 0;
var cultureLCID = 0; var cultureLCID = 0;
...@@ -49,6 +49,7 @@ public static async Task<RemoteHostClient> CreateAsync(Workspace workspace, bool ...@@ -49,6 +49,7 @@ public static async Task<RemoteHostClient> CreateAsync(Workspace workspace, bool
} }
private InProcRemoteHostClient( private InProcRemoteHostClient(
string clientId,
Workspace workspace, Workspace workspace,
InProcRemoteServices inprocServices, InProcRemoteServices inprocServices,
ReferenceCountedDisposable<RemotableDataJsonRpc> remotableDataRpc, ReferenceCountedDisposable<RemotableDataJsonRpc> remotableDataRpc,
...@@ -57,6 +58,8 @@ public static async Task<RemoteHostClient> CreateAsync(Workspace workspace, bool ...@@ -57,6 +58,8 @@ public static async Task<RemoteHostClient> CreateAsync(Workspace workspace, bool
{ {
Contract.ThrowIfNull(remotableDataRpc); Contract.ThrowIfNull(remotableDataRpc);
ClientId = clientId;
_inprocServices = inprocServices; _inprocServices = inprocServices;
_remotableDataRpc = remotableDataRpc; _remotableDataRpc = remotableDataRpc;
...@@ -76,6 +79,8 @@ public void RegisterService(string name, Func<Stream, IServiceProvider, ServiceH ...@@ -76,6 +79,8 @@ public void RegisterService(string name, Func<Stream, IServiceProvider, ServiceH
_inprocServices.RegisterService(name, serviceCreator); _inprocServices.RegisterService(name, serviceCreator);
} }
public override string ClientId { get; }
public override async Task<Connection> TryCreateConnectionAsync( public override async Task<Connection> TryCreateConnectionAsync(
string serviceName, object callbackTarget, CancellationToken cancellationToken) string serviceName, object callbackTarget, CancellationToken cancellationToken)
{ {
......
...@@ -57,6 +57,8 @@ private partial class ConnectionManager ...@@ -57,6 +57,8 @@ private partial class ConnectionManager
_shutdownLock = new ReaderWriterLockSlim(LockRecursionPolicy.NoRecursion); _shutdownLock = new ReaderWriterLockSlim(LockRecursionPolicy.NoRecursion);
} }
public HostGroup HostGroup => _hostGroup;
public Task<Connection> TryCreateConnectionAsync(string serviceName, object callbackTarget, CancellationToken cancellationToken) public Task<Connection> TryCreateConnectionAsync(string serviceName, object callbackTarget, CancellationToken cancellationToken)
{ {
// pool is not enabled by option // pool is not enabled by option
......
...@@ -7,7 +7,6 @@ ...@@ -7,7 +7,6 @@
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.Editor.Shared.Utilities;
using Microsoft.CodeAnalysis.Host; using Microsoft.CodeAnalysis.Host;
using Microsoft.CodeAnalysis.Internal.Log; using Microsoft.CodeAnalysis.Internal.Log;
using Microsoft.CodeAnalysis.Notification; using Microsoft.CodeAnalysis.Notification;
...@@ -30,8 +29,6 @@ private enum GlobalNotificationState ...@@ -30,8 +29,6 @@ private enum GlobalNotificationState
Finished Finished
} }
private static int s_instanceId = 0;
private readonly JsonRpc _rpc; private readonly JsonRpc _rpc;
private readonly ConnectionManager _connectionManager; private readonly ConnectionManager _connectionManager;
...@@ -75,9 +72,7 @@ public static async Task<ServiceHubRemoteHostClient> CreateWorkerAsync(Workspace ...@@ -75,9 +72,7 @@ public static async Task<ServiceHubRemoteHostClient> CreateWorkerAsync(Workspace
try try
{ {
// let each client to have unique id so that we can distinguish different clients when service is restarted // 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 = CreateClientId(Process.GetCurrentProcess().Id.ToString());
var current = $"VS ({Process.GetCurrentProcess().Id}) ({currentInstanceId})";
var hostGroup = new HostGroup(current); var hostGroup = new HostGroup(current);
var remoteHostStream = await Connections.RequestServiceAsync(workspace, primary, WellKnownRemoteHostServices.RemoteHostService, hostGroup, timeout, cancellationToken).ConfigureAwait(false); var remoteHostStream = await Connections.RequestServiceAsync(workspace, primary, WellKnownRemoteHostServices.RemoteHostService, hostGroup, timeout, cancellationToken).ConfigureAwait(false);
...@@ -133,6 +128,8 @@ public static async Task<ServiceHubRemoteHostClient> CreateWorkerAsync(Workspace ...@@ -133,6 +128,8 @@ public static async Task<ServiceHubRemoteHostClient> CreateWorkerAsync(Workspace
_rpc.StartListening(); _rpc.StartListening();
} }
public override string ClientId => _connectionManager.HostGroup.Id;
public override Task<Connection> TryCreateConnectionAsync(string serviceName, object callbackTarget, CancellationToken cancellationToken) public override Task<Connection> TryCreateConnectionAsync(string serviceName, object callbackTarget, CancellationToken cancellationToken)
{ {
return _connectionManager.TryCreateConnectionAsync(serviceName, callbackTarget, cancellationToken); return _connectionManager.TryCreateConnectionAsync(serviceName, callbackTarget, cancellationToken);
...@@ -158,6 +155,15 @@ protected override void OnStopped() ...@@ -158,6 +155,15 @@ protected override void OnStopped()
_connectionManager.Shutdown(); _connectionManager.Shutdown();
} }
public HostGroup HostGroup
{
get
{
Debug.Assert(_connectionManager.HostGroup.Id == ClientId);
return _connectionManager.HostGroup;
}
}
private void RegisterGlobalOperationNotifications() private void RegisterGlobalOperationNotifications()
{ {
var globalOperationService = this.Workspace.Services.GetService<IGlobalOperationNotificationService>(); var globalOperationService = this.Workspace.Services.GetService<IGlobalOperationNotificationService>();
...@@ -295,4 +301,4 @@ private void OnRpcDisconnected(object sender, JsonRpcDisconnectedEventArgs e) ...@@ -295,4 +301,4 @@ private void OnRpcDisconnected(object sender, JsonRpcDisconnectedEventArgs e)
Stopped(); Stopped();
} }
} }
} }
\ No newline at end of file
...@@ -52,6 +52,26 @@ public async Task Enable_Disable() ...@@ -52,6 +52,26 @@ public async Task Enable_Disable()
Assert.Null(disabledClient); Assert.Null(disabledClient);
} }
[Fact, Trait(Traits.Feature, Traits.Features.RemoteHost)]
public async Task ClientId()
{
var service = CreateRemoteHostClientService();
service.Enable();
var client1 = await service.TryGetRemoteHostClientAsync(CancellationToken.None);
var id1 = client1.ClientId;
await service.RequestNewRemoteHostAsync(CancellationToken.None);
var client2 = await service.TryGetRemoteHostClientAsync(CancellationToken.None);
var id2 = client2.ClientId;
Assert.NotEqual(id1, id2);
service.Disable();
}
[Fact, Trait(Traits.Feature, Traits.Features.RemoteHost)] [Fact, Trait(Traits.Feature, Traits.Features.RemoteHost)]
public async Task GlobalAssets() public async Task GlobalAssets()
{ {
......
...@@ -26,6 +26,14 @@ protected RemoteHostClient(Workspace workspace) ...@@ -26,6 +26,14 @@ protected RemoteHostClient(Workspace workspace)
public event EventHandler<bool> StatusChanged; public event EventHandler<bool> StatusChanged;
/// <summary>
/// Return an unique string per client.
///
/// one can use this to distinguish different clients that are connected to different RemoteHosts including
/// cases where 2 external process finding each others
/// </summary>
public abstract string ClientId { get; }
/// <summary> /// <summary>
/// Create <see cref="RemoteHostClient.Connection"/> for the <paramref name="serviceName"/> if possible. /// Create <see cref="RemoteHostClient.Connection"/> for the <paramref name="serviceName"/> if possible.
/// otherwise, return null. /// otherwise, return null.
...@@ -64,6 +72,11 @@ private void OnStatusChanged(bool started) ...@@ -64,6 +72,11 @@ private void OnStatusChanged(bool started)
StatusChanged?.Invoke(this, started); StatusChanged?.Invoke(this, started);
} }
public static string CreateClientId(string prefix)
{
return $"VS ({prefix}) ({Guid.NewGuid().ToString()})";
}
/// <summary> /// <summary>
/// NoOpClient is used if a user killed our remote host process. Basically this client never /// NoOpClient is used if a user killed our remote host process. Basically this client never
/// create a session /// create a session
...@@ -75,6 +88,8 @@ public class NoOpClient : RemoteHostClient ...@@ -75,6 +88,8 @@ public class NoOpClient : RemoteHostClient
{ {
} }
public override string ClientId => nameof(NoOpClient);
public override Task<Connection> TryCreateConnectionAsync(string serviceName, object callbackTarget, CancellationToken cancellationToken) public override Task<Connection> TryCreateConnectionAsync(string serviceName, object callbackTarget, CancellationToken cancellationToken)
{ {
return SpecializedTasks.Default<Connection>(); return SpecializedTasks.Default<Connection>();
...@@ -140,7 +155,7 @@ public void Dispose() ...@@ -140,7 +155,7 @@ public void Dispose()
// when that happen, we don't want to crash VS, so this is debug only check // when that happen, we don't want to crash VS, so this is debug only check
if (!Environment.HasShutdownStarted) if (!Environment.HasShutdownStarted)
{ {
Debug.Assert(false, Debug.Assert(false,
$"Unless OOP process (RoslynCodeAnalysisService) is explicitly killed, this should have been disposed!\r\n {_creationCallStack}"); $"Unless OOP process (RoslynCodeAnalysisService) is explicitly killed, this should have been disposed!\r\n {_creationCallStack}");
} }
} }
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册