Skip to content

Startup task tweaks #1203

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 7 commits into from
Feb 26, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -238,7 +238,8 @@ protected override void EndProcessing()
using (var psesLoader = EditorServicesLoader.Create(_logger, editorServicesConfig, sessionFileWriter, _loggerUnsubscribers))
{
_logger.Log(PsesLogLevel.Verbose, "Loading EditorServices");
psesLoader.LoadAndRunEditorServicesAsync().Wait();
// Start editor services and wait here until it shuts down
psesLoader.LoadAndRunEditorServicesAsync().GetAwaiter().GetResult();
}
}
catch (Exception e)
Expand Down Expand Up @@ -432,20 +433,20 @@ private ITransportConfig GetLanguageServiceTransport()

if (Stdio)
{
return new StdioTransportConfig();
return new StdioTransportConfig(_logger);
}

if (LanguageServiceInPipeName != null && LanguageServiceOutPipeName != null)
{
return SimplexNamedPipeTransportConfig.Create(LanguageServiceInPipeName, LanguageServiceOutPipeName);
return SimplexNamedPipeTransportConfig.Create(_logger, LanguageServiceInPipeName, LanguageServiceOutPipeName);
}

if (SplitInOutPipes)
{
return SimplexNamedPipeTransportConfig.Create(LanguageServicePipeName);
return SimplexNamedPipeTransportConfig.Create(_logger, LanguageServicePipeName);
}

return DuplexNamedPipeTransportConfig.Create(LanguageServicePipeName);
return DuplexNamedPipeTransportConfig.Create(_logger, LanguageServicePipeName);
}

private ITransportConfig GetDebugServiceTransport()
Expand All @@ -456,7 +457,7 @@ private ITransportConfig GetDebugServiceTransport()
{
if (DebugServiceOnly)
{
return new StdioTransportConfig();
return new StdioTransportConfig(_logger);
}

_logger.Log(PsesLogLevel.Diagnostic, "No debug transport: Transport is Stdio with debug disabled");
Expand All @@ -465,15 +466,15 @@ private ITransportConfig GetDebugServiceTransport()

if (DebugServiceInPipeName != null && DebugServiceOutPipeName != null)
{
return SimplexNamedPipeTransportConfig.Create(DebugServiceInPipeName, DebugServiceOutPipeName);
return SimplexNamedPipeTransportConfig.Create(_logger, DebugServiceInPipeName, DebugServiceOutPipeName);
}

if (SplitInOutPipes)
{
return SimplexNamedPipeTransportConfig.Create(DebugServicePipeName);
return SimplexNamedPipeTransportConfig.Create(_logger, DebugServicePipeName);
}

return DuplexNamedPipeTransportConfig.Create(DebugServicePipeName);
return DuplexNamedPipeTransportConfig.Create(_logger, DebugServicePipeName);
}

private enum ProfileHostKind
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -363,7 +363,7 @@ private void RunWriter()
_fileWriter.WriteLine(logMessage);
}
}
catch (TaskCanceledException)
catch (OperationCanceledException)
{
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,13 @@ public interface ITransportConfig
/// </summary>
public sealed class StdioTransportConfig : ITransportConfig
{
private readonly HostLogger _logger;

public StdioTransportConfig(HostLogger logger)
{
_logger = logger;
}

public string EndpointDetails => "<stdio>";

public string SessionFileTransportName => "Stdio";
Expand All @@ -51,6 +58,7 @@ public sealed class StdioTransportConfig : ITransportConfig

public Task<(Stream inStream, Stream outStream)> ConnectStreamsAsync()
{
_logger.Log(PsesLogLevel.Diagnostic, "Connecting stdio streams");
return Task.FromResult((Console.OpenStandardInput(), Console.OpenStandardOutput()));
}
}
Expand All @@ -64,29 +72,32 @@ public sealed class DuplexNamedPipeTransportConfig : ITransportConfig
/// Create a duplex named pipe transport config with an automatically generated pipe name.
/// </summary>
/// <returns>A new duplex named pipe transport configuration.</returns>
public static DuplexNamedPipeTransportConfig Create()
public static DuplexNamedPipeTransportConfig Create(HostLogger logger)
{
return new DuplexNamedPipeTransportConfig(NamedPipeUtils.GenerateValidNamedPipeName());
return new DuplexNamedPipeTransportConfig(logger, NamedPipeUtils.GenerateValidNamedPipeName());
}

/// <summary>
/// Create a duplex named pipe transport config with the given pipe name.
/// </summary>
/// <returns>A new duplex named pipe transport configuration.</returns>
public static DuplexNamedPipeTransportConfig Create(string pipeName)
public static DuplexNamedPipeTransportConfig Create(HostLogger logger, string pipeName)
{
if (pipeName == null)
{
return DuplexNamedPipeTransportConfig.Create();
return DuplexNamedPipeTransportConfig.Create(logger);
}

return new DuplexNamedPipeTransportConfig(pipeName);
return new DuplexNamedPipeTransportConfig(logger, pipeName);
}

private readonly HostLogger _logger;

private readonly string _pipeName;

private DuplexNamedPipeTransportConfig(string pipeName)
private DuplexNamedPipeTransportConfig(HostLogger logger, string pipeName)
{
_logger = logger;
_pipeName = pipeName;
SessionFileEntries = new Dictionary<string, object>{ { "PipeName", NamedPipeUtils.GetNamedPipePath(pipeName) } };
}
Expand All @@ -99,8 +110,11 @@ private DuplexNamedPipeTransportConfig(string pipeName)

public async Task<(Stream inStream, Stream outStream)> ConnectStreamsAsync()
{
_logger.Log(PsesLogLevel.Diagnostic, "Creating named pipe");
NamedPipeServerStream namedPipe = NamedPipeUtils.CreateNamedPipe(_pipeName, PipeDirection.InOut);
_logger.Log(PsesLogLevel.Diagnostic, "Waiting for named pipe connection");
await namedPipe.WaitForConnectionAsync().ConfigureAwait(false);
_logger.Log(PsesLogLevel.Diagnostic, "Named pipe connected");
return (namedPipe, namedPipe);
}
}
Expand All @@ -117,42 +131,44 @@ public sealed class SimplexNamedPipeTransportConfig : ITransportConfig
/// Create a pair of simplex named pipes using generated names.
/// </summary>
/// <returns>A new simplex named pipe transport config.</returns>
public static SimplexNamedPipeTransportConfig Create()
public static SimplexNamedPipeTransportConfig Create(HostLogger logger)
{
return SimplexNamedPipeTransportConfig.Create(NamedPipeUtils.GenerateValidNamedPipeName(new[] { InPipePrefix, OutPipePrefix }));
return SimplexNamedPipeTransportConfig.Create(logger, NamedPipeUtils.GenerateValidNamedPipeName(new[] { InPipePrefix, OutPipePrefix }));
}

/// <summary>
/// Create a pair of simplex named pipes using the given name as a base.
/// </summary>
/// <returns>A new simplex named pipe transport config.</returns>
public static SimplexNamedPipeTransportConfig Create(string pipeNameBase)
public static SimplexNamedPipeTransportConfig Create(HostLogger logger, string pipeNameBase)
{
if (pipeNameBase == null)
{
return SimplexNamedPipeTransportConfig.Create();
return SimplexNamedPipeTransportConfig.Create(logger);
}

string inPipeName = $"{InPipePrefix}_{pipeNameBase}";
string outPipeName = $"{OutPipePrefix}_{pipeNameBase}";

return SimplexNamedPipeTransportConfig.Create(inPipeName, outPipeName);
return SimplexNamedPipeTransportConfig.Create(logger, inPipeName, outPipeName);
}

/// <summary>
/// Create a pair of simplex named pipes using the given names.
/// </summary>
/// <returns>A new simplex named pipe transport config.</returns>
public static SimplexNamedPipeTransportConfig Create(string inPipeName, string outPipeName)
public static SimplexNamedPipeTransportConfig Create(HostLogger logger, string inPipeName, string outPipeName)
{
return new SimplexNamedPipeTransportConfig(inPipeName, outPipeName);
return new SimplexNamedPipeTransportConfig(logger, inPipeName, outPipeName);
}

private readonly HostLogger _logger;
private readonly string _inPipeName;
private readonly string _outPipeName;

private SimplexNamedPipeTransportConfig(string inPipeName, string outPipeName)
private SimplexNamedPipeTransportConfig(HostLogger logger, string inPipeName, string outPipeName)
{
_logger = logger;
_inPipeName = inPipeName;
_outPipeName = outPipeName;

Expand All @@ -171,14 +187,18 @@ private SimplexNamedPipeTransportConfig(string inPipeName, string outPipeName)

public async Task<(Stream inStream, Stream outStream)> ConnectStreamsAsync()
{
_logger.Log(PsesLogLevel.Diagnostic, "Starting in pipe connection");
NamedPipeServerStream inPipe = NamedPipeUtils.CreateNamedPipe(_inPipeName, PipeDirection.InOut);
Task inPipeConnected = inPipe.WaitForConnectionAsync();

_logger.Log(PsesLogLevel.Diagnostic, "Starting out pipe connection");
NamedPipeServerStream outPipe = NamedPipeUtils.CreateNamedPipe(_outPipeName, PipeDirection.Out);
Task outPipeConnected = outPipe.WaitForConnectionAsync();

_logger.Log(PsesLogLevel.Diagnostic, "Wating for pipe connections");
await Task.WhenAll(inPipeConnected, outPipeConnected).ConfigureAwait(false);

_logger.Log(PsesLogLevel.Diagnostic, "Simplex named pipe transport connected");
return (inPipe, outPipe);
}
}
Expand Down
25 changes: 16 additions & 9 deletions src/PowerShellEditorServices.Hosting/EditorServicesLoader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,8 @@ public static EditorServicesLoader Create(

private readonly IReadOnlyCollection<IDisposable> _loggersToUnsubscribe;

private EditorServicesRunner _editorServicesRunner;

private EditorServicesLoader(
HostLogger logger,
EditorServicesConfig hostConfig,
Expand All @@ -177,7 +179,7 @@ private EditorServicesLoader(
/// This method's returned task will end when Editor Services shuts down.
/// </summary>
/// <returns></returns>
public async Task LoadAndRunEditorServicesAsync()
public Task LoadAndRunEditorServicesAsync()
{
// Log important host information here
LogHostInformation();
Expand All @@ -200,22 +202,27 @@ public async Task LoadAndRunEditorServicesAsync()
LoadEditorServices();

_logger.Log(PsesLogLevel.Verbose, "Starting EditorServices");
using (var editorServicesRunner = new EditorServicesRunner(_logger, _hostConfig, _sessionFileWriter, _loggersToUnsubscribe))
{
// The trigger method for Editor Services
// We will wait here until Editor Services shuts down
await editorServicesRunner.RunUntilShutdown().ConfigureAwait(false);
}

_editorServicesRunner = new EditorServicesRunner(_logger, _hostConfig, _sessionFileWriter, _loggersToUnsubscribe);

// The trigger method for Editor Services
return Task.Run(_editorServicesRunner.RunUntilShutdown);
}

public void Dispose()
{
// TODO: Remove assembly resolve events
// This is not high priority, since the PSES process shouldn't be reused
_logger.Log(PsesLogLevel.Diagnostic, "Loader disposed");
_editorServicesRunner?.Dispose();

// TODO:
// Remove assembly resolve events
// This is not high priority, since the PSES process shouldn't be reused
}

private void LoadEditorServices()
{
// This must be in its own method, since the actual load happens when the calling method is called
// The call within this method is therefore a total no-op
EditorServicesLoading.LoadEditorServicesForHost();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ public EditorServicesRunner(
/// Start and run Editor Services and then wait for shutdown.
/// </summary>
/// <returns>A task that ends when Editor Services shuts down.</returns>
public async Task RunUntilShutdown()
public Task RunUntilShutdown()
{
// Start Editor Services
Task runAndAwaitShutdown = CreateEditorServicesAndRunUntilShutdown();
Expand All @@ -57,7 +57,8 @@ public async Task RunUntilShutdown()
_sessionFileWriter.WriteSessionStarted(_config.LanguageServiceTransport, _config.DebugServiceTransport);

// Finally, wait for Editor Services to shut down
await runAndAwaitShutdown.ConfigureAwait(false);
_logger.Log(PsesLogLevel.Diagnostic, "Waiting on PSES run/shutdown");
return runAndAwaitShutdown;
}

public void Dispose()
Expand All @@ -73,6 +74,8 @@ private async Task CreateEditorServicesAndRunUntilShutdown()
{
try
{
_logger.Log(PsesLogLevel.Diagnostic, "Creating/running editor services");

bool creatingLanguageServer = _config.LanguageServiceTransport != null;
bool creatingDebugServer = _config.DebugServiceTransport != null;
bool isTempDebugSession = creatingDebugServer && !creatingLanguageServer;
Expand Down