From 1850021543074d821e35aadba6365536af23f7d1 Mon Sep 17 00:00:00 2001 From: Sung Yoon Whang Date: Sat, 7 Nov 2020 12:27:17 -0800 Subject: [PATCH] Clean up reversed server sockets upon exit (#1704) --- .../ReversedServerHelpers.cs | 19 +++++++++----- src/Tools/dotnet-counters/CounterMonitor.cs | 26 ++++++++++++------- .../CommandLine/Commands/CollectCommand.cs | 13 +++++++--- 3 files changed, 40 insertions(+), 18 deletions(-) diff --git a/src/Tools/Common/ReversedServerHelpers/ReversedServerHelpers.cs b/src/Tools/Common/ReversedServerHelpers/ReversedServerHelpers.cs index 0f368d89c..ff74a7e3e 100644 --- a/src/Tools/Common/ReversedServerHelpers/ReversedServerHelpers.cs +++ b/src/Tools/Common/ReversedServerHelpers/ReversedServerHelpers.cs @@ -96,7 +96,7 @@ namespace Microsoft.Internal.Common.Utils return true; } - public void Cleanup() + public async void Cleanup() { if (_childProc != null && !_childProc.HasExited) { @@ -107,6 +107,11 @@ namespace Microsoft.Internal.Common.Utils // if process exited while we were trying to kill it, it can throw IOE catch (InvalidOperationException) { } } + + if (ReversedDiagnosticsClientBuilder.Server != null) + { + await ReversedDiagnosticsClientBuilder.Server.DisposeAsync(); + } } } @@ -117,6 +122,8 @@ namespace Microsoft.Internal.Common.Utils { private static string GetTransportName(string toolName) => $"{toolName}-{Process.GetCurrentProcess().Id}-{DateTime.Now:yyyyMMdd_HHmmss}.socket"; + public static ReversedDiagnosticsServer Server = null; + // // Starts the child process and returns the diagnostics client once the child proc connects to the reversed diagnostics pipe. // The callee needs to resume the diagnostics client at appropriate time. @@ -129,8 +136,8 @@ namespace Microsoft.Internal.Common.Utils } // Create and start the reversed server string diagnosticTransportName = GetTransportName(toolName); - ReversedDiagnosticsServer server = new ReversedDiagnosticsServer(diagnosticTransportName); - server.Start(); + Server = new ReversedDiagnosticsServer(diagnosticTransportName); + Server.Start(); // Start the child proc if (!childProcLauncher.Start(diagnosticTransportName)) @@ -139,14 +146,14 @@ namespace Microsoft.Internal.Common.Utils } // Wait for attach - IpcEndpointInfo endpointInfo = server.Accept(TimeSpan.FromSeconds(timeoutInSec)); + IpcEndpointInfo endpointInfo = Server.Accept(TimeSpan.FromSeconds(timeoutInSec)); // If for some reason a different process attached to us, wait until the expected process attaches. while (endpointInfo.ProcessId != childProcLauncher.ChildProc.Id) { - endpointInfo = server.Accept(TimeSpan.FromSeconds(timeoutInSec)); + endpointInfo = Server.Accept(TimeSpan.FromSeconds(timeoutInSec)); } return new DiagnosticsClient(endpointInfo.Endpoint); } } -} \ No newline at end of file +} diff --git a/src/Tools/dotnet-counters/CounterMonitor.cs b/src/Tools/dotnet-counters/CounterMonitor.cs index 5bdb84079..974013ba7 100644 --- a/src/Tools/dotnet-counters/CounterMonitor.cs +++ b/src/Tools/dotnet-counters/CounterMonitor.cs @@ -95,6 +95,7 @@ namespace Microsoft.Diagnostics.Tools.Counters return 0; } + int ret = 0; try { InitializeCounterList(counters, counter_list); @@ -104,11 +105,10 @@ namespace Microsoft.Diagnostics.Tools.Counters _renderer = new ConsoleWriter(); if (!BuildDiagnosticsClient()) { - return 0; + ret = 0; } - int ret = await Start(); + ret = await Start(); ProcessLauncher.Launcher.Cleanup(); - return ret; } catch (OperationCanceledException) { @@ -119,13 +119,19 @@ namespace Microsoft.Diagnostics.Tools.Counters catch (Exception) {} // Swallow all exceptions for now. console.Out.WriteLine($"Complete"); - return 1; + ret = 1; + } + finally + { + ProcessLauncher.Launcher.Cleanup(); } + return ret; } public async Task Collect(CancellationToken ct, List counter_list, string counters, IConsole console, int processId, int refreshInterval, CountersExportFormat format, string output, string name) { + int ret = 1; if (!ValidateAndSetProcessId(processId, name)) { return 0; @@ -145,6 +151,7 @@ namespace Microsoft.Diagnostics.Tools.Counters if (!BuildDiagnosticsClient()) { + ProcessLauncher.Launcher.Cleanup(); return 0; } @@ -172,15 +179,16 @@ namespace Microsoft.Diagnostics.Tools.Counters _console.Error.WriteLine($"The output format {format} is not a valid output format."); return 0; } - - int ret = await Start(); - ProcessLauncher.Launcher.Cleanup(); - return ret; + ret = await Start(); } catch (OperationCanceledException) { } - return 1; + finally + { + ProcessLauncher.Launcher.Cleanup(); + } + return ret; } private void InitializeCounterList(string counters, List counterList) diff --git a/src/Tools/dotnet-trace/CommandLine/Commands/CollectCommand.cs b/src/Tools/dotnet-trace/CommandLine/Commands/CollectCommand.cs index 2f70022d5..251116f7f 100644 --- a/src/Tools/dotnet-trace/CommandLine/Commands/CollectCommand.cs +++ b/src/Tools/dotnet-trace/CommandLine/Commands/CollectCommand.cs @@ -41,6 +41,7 @@ namespace Microsoft.Diagnostics.Tools.Trace /// private static async Task Collect(CancellationToken ct, IConsole console, int processId, FileInfo output, uint buffersize, string providers, string profile, TraceFileFormat format, TimeSpan duration, string clrevents, string clreventlevel, string name) { + int ret = 0; try { Debug.Assert(output != null); @@ -141,6 +142,7 @@ namespace Microsoft.Diagnostics.Tools.Trace { ProcessLauncher.Launcher.ChildProc.Kill(); } + await ReversedDiagnosticsClientBuilder.Server.DisposeAsync(); return ErrorCodes.SessionCreationError; } process = ProcessLauncher.Launcher.ChildProc; @@ -253,12 +255,13 @@ namespace Microsoft.Diagnostics.Tools.Trace if (format != TraceFileFormat.NetTrace) TraceFileFormatConverter.ConvertToFormat(format, output.FullName); + ret = 0; } } catch (Exception ex) { Console.Error.WriteLine($"[ERROR] {ex.ToString()}"); - return ErrorCodes.TracingError; + ret = ErrorCodes.TracingError; } finally { @@ -270,9 +273,13 @@ namespace Microsoft.Diagnostics.Tools.Trace { ProcessLauncher.Launcher.ChildProc.Kill(); } - } - return await Task.FromResult(0); + if (ReversedDiagnosticsClientBuilder.Server != null) + { + await ReversedDiagnosticsClientBuilder.Server.DisposeAsync(); + } + } + return await Task.FromResult(ret); } private static void PrintProviders(IReadOnlyList providers, Dictionary enabledBy) -- 2.34.1