Skip to content

Commit fc25e18

Browse files
Disconnect support and handling of JsonRpcServer teardown
1 parent a6c1a0e commit fc25e18

File tree

6 files changed

+136
-56
lines changed

6 files changed

+136
-56
lines changed

global.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{
22
"sdk": {
3-
"version": "2.1.602"
3+
"version": "2.1.801"
44
}
55
}

src/PowerShellEditorServices.Engine/Hosting/EditorServicesHost.cs

Lines changed: 51 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -280,6 +280,8 @@ public void StartLanguageService(
280280
config.TransportType, config.Endpoint));
281281
}
282282

283+
284+
private bool alreadySubscribedDebug;
283285
/// <summary>
284286
/// Starts the debug service with the specified config.
285287
/// </summary>
@@ -291,48 +293,55 @@ public void StartDebugService(
291293
ProfilePaths profilePaths,
292294
bool useExistingSession)
293295
{
294-
//while (!System.Diagnostics.Debugger.IsAttached)
295-
//{
296-
// System.Console.WriteLine($"{Process.GetCurrentProcess().Id}");
297-
// Thread.Sleep(2000);
298-
//}
299-
300-
//_logger.LogInformation($"Debug NamedPipe: {config.InOutPipeName}\nDebug OutPipe: {config.OutPipeName}");
301-
302-
//switch (config.TransportType)
303-
//{
304-
// case EditorServiceTransportType.NamedPipe:
305-
// NamedPipeServerStream inNamedPipe = CreateNamedPipe(
306-
// config.InOutPipeName ?? config.InPipeName,
307-
// config.OutPipeName,
308-
// out NamedPipeServerStream outNamedPipe);
309-
310-
// _debugServer = new PsesDebugServer(
311-
// _factory,
312-
// inNamedPipe,
313-
// outNamedPipe ?? inNamedPipe);
314-
315-
// Task[] tasks = outNamedPipe != null
316-
// ? new[] { inNamedPipe.WaitForConnectionAsync(), outNamedPipe.WaitForConnectionAsync() }
317-
// : new[] { inNamedPipe.WaitForConnectionAsync() };
318-
// Task.WhenAll(tasks)
319-
// .ContinueWith(async task => {
320-
// _logger.LogInformation("Starting debug server");
321-
// await _debugServer.StartAsync(_languageServer.LanguageServer.Services);
322-
// _logger.LogInformation(
323-
// $"Debug service started, type = {config.TransportType}, endpoint = {config.Endpoint}");
324-
// });
325-
// break;
326-
327-
// default:
328-
// throw new NotSupportedException("not supported");
329-
//}
330-
331-
//_debugServer.SessionEnded += (sender, eventArgs) =>
332-
//{
333-
// _debugServer.Dispose();
334-
// StartDebugService(config, profilePaths, useExistingSession);
335-
//};
296+
while (System.Diagnostics.Debugger.IsAttached)
297+
{
298+
System.Console.WriteLine($"{Process.GetCurrentProcess().Id}");
299+
Thread.Sleep(2000);
300+
}
301+
302+
_logger.LogInformation($"Debug NamedPipe: {config.InOutPipeName}\nDebug OutPipe: {config.OutPipeName}");
303+
304+
switch (config.TransportType)
305+
{
306+
case EditorServiceTransportType.NamedPipe:
307+
NamedPipeServerStream inNamedPipe = CreateNamedPipe(
308+
config.InOutPipeName ?? config.InPipeName,
309+
config.OutPipeName,
310+
out NamedPipeServerStream outNamedPipe);
311+
312+
_debugServer = new PsesDebugServer(
313+
_factory,
314+
inNamedPipe,
315+
outNamedPipe ?? inNamedPipe);
316+
317+
Task[] tasks = outNamedPipe != null
318+
? new[] { inNamedPipe.WaitForConnectionAsync(), outNamedPipe.WaitForConnectionAsync() }
319+
: new[] { inNamedPipe.WaitForConnectionAsync() };
320+
Task.WhenAll(tasks)
321+
.ContinueWith(async task =>
322+
{
323+
_logger.LogInformation("Starting debug server");
324+
await _debugServer.StartAsync(_languageServer.LanguageServer.Services);
325+
_logger.LogInformation(
326+
$"Debug service started, type = {config.TransportType}, endpoint = {config.Endpoint}");
327+
});
328+
329+
break;
330+
331+
default:
332+
throw new NotSupportedException("not supported");
333+
}
334+
335+
if(!alreadySubscribedDebug)
336+
{
337+
alreadySubscribedDebug = true;
338+
_debugServer.SessionEnded += (sender, eventArgs) =>
339+
{
340+
_debugServer.Dispose();
341+
alreadySubscribedDebug = false;
342+
StartDebugService(config, profilePaths, useExistingSession);
343+
};
344+
}
336345
}
337346

338347
/// <summary>

src/PowerShellEditorServices.Engine/Server/PsesDebugServer.cs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,15 +16,15 @@
1616

1717
namespace Microsoft.PowerShell.EditorServices.Engine.Server
1818
{
19-
internal class PsesDebugServer : IDisposable
19+
public class PsesDebugServer : IDisposable
2020
{
2121
protected readonly ILoggerFactory _loggerFactory;
2222
private readonly Stream _inputStream;
2323
private readonly Stream _outputStream;
2424

2525
private IJsonRpcServer _jsonRpcServer;
2626

27-
internal PsesDebugServer(
27+
public PsesDebugServer(
2828
ILoggerFactory factory,
2929
Stream inputStream,
3030
Stream outputStream)
@@ -44,6 +44,7 @@ public async Task StartAsync(IServiceProvider languageServerServiceProvider)
4444
ILogger logger = options.LoggerFactory.CreateLogger("DebugOptionsStartup");
4545
options.Services = new ServiceCollection()
4646
.AddSingleton(languageServerServiceProvider.GetService<PowerShellContextService>())
47+
.AddSingleton<PsesDebugServer>(this)
4748
.AddSingleton<DebugService>()
4849
.AddSingleton<DebugStateService>()
4950
.AddSingleton<DebugEventHandlerService>();
@@ -57,7 +58,8 @@ public async Task StartAsync(IServiceProvider languageServerServiceProvider)
5758
options
5859
.WithHandler<InitializeHandler>()
5960
.WithHandler<LaunchHandler>()
60-
.WithHandler<AttachHandler>();
61+
.WithHandler<AttachHandler>()
62+
.WithHandler<DisconnectHandler>();
6163

6264
logger.LogInformation("Handlers added");
6365
});
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
//
2+
// Copyright (c) Microsoft. All rights reserved.
3+
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
4+
//
5+
6+
using System;
7+
using System.Threading;
8+
using System.Threading.Tasks;
9+
using Microsoft.Extensions.Logging;
10+
using Microsoft.PowerShell.EditorServices.Engine.Logging;
11+
using Microsoft.PowerShell.EditorServices.Engine.Server;
12+
using Microsoft.PowerShell.EditorServices.Engine.Services;
13+
using Microsoft.PowerShell.EditorServices.Engine.Services.PowerShellContext;
14+
using OmniSharp.Extensions.DebugAdapter.Protocol.Requests;
15+
16+
namespace Microsoft.PowerShell.EditorServices.Engine.Handlers
17+
{
18+
public class DisconnectHandler : IDisconnectHandler
19+
{
20+
private readonly ILogger<DisconnectHandler> _logger;
21+
private readonly PowerShellContextService _powerShellContextService;
22+
private readonly DebugStateService _debugStateService;
23+
private readonly DebugEventHandlerService _debugEventHandlerService;
24+
private readonly PsesDebugServer _psesDebugServer;
25+
26+
public DisconnectHandler(
27+
ILoggerFactory factory,
28+
PsesDebugServer psesDebugServer,
29+
PowerShellContextService powerShellContextService,
30+
DebugStateService debugStateService,
31+
DebugEventHandlerService debugEventHandlerService)
32+
{
33+
_logger = factory.CreateLogger<DisconnectHandler>();
34+
_psesDebugServer = psesDebugServer;
35+
_powerShellContextService = powerShellContextService;
36+
_debugStateService = debugStateService;
37+
_debugEventHandlerService = debugEventHandlerService;
38+
}
39+
40+
public async Task<DisconnectResponse> Handle(DisconnectArguments request, CancellationToken cancellationToken)
41+
{
42+
_debugEventHandlerService.UnregisterEventHandlers();
43+
if (_debugStateService.ExecutionCompleted == false)
44+
{
45+
_debugStateService.ExecutionCompleted = true;
46+
_powerShellContextService.AbortExecution(shouldAbortDebugSession: true);
47+
48+
if (_debugStateService.IsInteractiveDebugSession && _debugStateService.IsAttachSession)
49+
{
50+
// Pop the sessions
51+
if (_powerShellContextService.CurrentRunspace.Context == RunspaceContext.EnteredProcess)
52+
{
53+
try
54+
{
55+
await _powerShellContextService.ExecuteScriptStringAsync("Exit-PSHostProcess");
56+
57+
if (_debugStateService.IsRemoteAttach &&
58+
_powerShellContextService.CurrentRunspace.Location == RunspaceLocation.Remote)
59+
{
60+
await _powerShellContextService.ExecuteScriptStringAsync("Exit-PSSession");
61+
}
62+
}
63+
catch (Exception e)
64+
{
65+
_logger.LogException("Caught exception while popping attached process after debugging", e);
66+
}
67+
}
68+
}
69+
}
70+
71+
_logger.LogInformation("Debug adapter is shutting down...");
72+
73+
// Trigger the clean up of the debugger.
74+
Task.Run(_psesDebugServer.OnSessionEnded);
75+
76+
return new DisconnectResponse();
77+
}
78+
}
79+
}

src/PowerShellEditorServices.Engine/Services/DebugAdapter/Handlers/InitializeHandler.cs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77
using System.Threading.Tasks;
88
using Microsoft.Extensions.Logging;
99
using Microsoft.PowerShell.EditorServices.Engine.Services;
10-
using OmniSharp.Extensions.DebugAdapter.Protocol.Models;
1110
using OmniSharp.Extensions.DebugAdapter.Protocol.Requests;
1211

1312
namespace Microsoft.PowerShell.EditorServices.Engine.Handlers

src/PowerShellEditorServices.Engine/Services/DebugAdapter/Handlers/LaunchAndAttachHandler.cs

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -399,15 +399,6 @@ private async Task OnExecutionCompletedAsync(Task executeTask)
399399
}
400400

401401
_debugService.IsClientAttached = false;
402-
403-
//if (_disconnectRequestContext != null)
404-
//{
405-
// // Respond to the disconnect request and stop the server
406-
// await _disconnectRequestContext.SendResultAsync(null);
407-
// Stop();
408-
// return;
409-
//}
410-
411402
_jsonRpcServer.SendNotification(EventNames.Terminated);
412403
}
413404
}

0 commit comments

Comments
 (0)