From 5f5b42744b369bfe0603cda4fb59a3e8129bbb3c Mon Sep 17 00:00:00 2001 From: Juan Sebastian Hoyos Ayala Date: Fri, 23 May 2025 01:37:22 -0700 Subject: [PATCH] Check for process exit as well as pipe message in test runners --- src/SOS/SOS.UnitTests/SOSRunner.cs | 3 ++- src/tests/CommonTestRunner/TestRunner.cs | 12 ++++++++++-- src/tests/DbgShim.UnitTests/DebuggeeInfo.cs | 16 ++++++++++++++-- 3 files changed, 26 insertions(+), 5 deletions(-) diff --git a/src/SOS/SOS.UnitTests/SOSRunner.cs b/src/SOS/SOS.UnitTests/SOSRunner.cs index 4d92aff541..647bb08fb7 100644 --- a/src/SOS/SOS.UnitTests/SOSRunner.cs +++ b/src/SOS/SOS.UnitTests/SOSRunner.cs @@ -378,9 +378,10 @@ public static async Task CreateDump(TestInformation information) if (pipeServer != null) { dotnetDumpOutputHelper.WriteLine("Waiting for connection on pipe {0}", pipeName); - CancellationTokenSource source = new(TimeSpan.FromMinutes(5)); + using CancellationTokenSource source = new(TimeSpan.FromMinutes(5)); // Wait for debuggee to connect/write to pipe or if the process exits on some other failure/abnormally + // TODO: This is a resiliency issue - we'll try to collect the dump even if the debuggee fails to connect. await Task.WhenAny(pipeServer.WaitForConnectionAsync(source.Token), processRunner.WaitForExit()); } diff --git a/src/tests/CommonTestRunner/TestRunner.cs b/src/tests/CommonTestRunner/TestRunner.cs index a552385a6a..730dac25d1 100644 --- a/src/tests/CommonTestRunner/TestRunner.cs +++ b/src/tests/CommonTestRunner/TestRunner.cs @@ -245,8 +245,16 @@ public async Task WaitForTracee() WriteLine("WaitForTracee"); try { - CancellationTokenSource source = new(TimeSpan.FromMinutes(2)); - await _pipeServer.WaitForConnectionAsync(source.Token).ConfigureAwait(false); + using CancellationTokenSource source = new(TimeSpan.FromMinutes(2)); + Task processDeath = _runner.WaitForExit(); + Task traceeReady = _pipeServer.WaitForConnectionAsync(source.Token); + Task doneTask = await Task.WhenAny(processDeath, traceeReady).WaitAsync(source.Token).ConfigureAwait(false); + + source.Cancel(); + if (doneTask == processDeath) + { + Trace.TraceWarning($"WaitForTracee: process {Pid} exited without sending the event"); + } WriteLine("WaitForTracee: DONE"); } catch (Exception ex) when (ex is TaskCanceledException or OperationCanceledException) diff --git a/src/tests/DbgShim.UnitTests/DebuggeeInfo.cs b/src/tests/DbgShim.UnitTests/DebuggeeInfo.cs index b60e30ed6c..48588a6c64 100644 --- a/src/tests/DbgShim.UnitTests/DebuggeeInfo.cs +++ b/src/tests/DbgShim.UnitTests/DebuggeeInfo.cs @@ -71,9 +71,21 @@ public async Task WaitForDebuggee() } try { - CancellationTokenSource source = new(TimeSpan.FromMinutes(5)); + using CancellationTokenSource source = new(TimeSpan.FromMinutes(5)); Trace.TraceInformation($"DebuggeeInfo.WaitForDebuggee: waiting {ProcessId}"); - await _pipeServer.WaitForConnectionAsync(source.Token); + + Task processDeath = _process.WaitForExitAsync(source.Token); + Task debuggeeReady = _pipeServer.WaitForConnectionAsync(source.Token); + Task doneTask = await Task.WhenAny(processDeath, debuggeeReady).WaitAsync(source.Token); + + source.Cancel(); + + if (doneTask == processDeath) + { + Trace.TraceWarning($"DebuggeeInfo.WaitForDebuggee: process {ProcessId} exited"); + return false; + } + Trace.TraceInformation($"DebuggeeInfo.WaitForDebuggee: after wait {ProcessId}"); } catch (Exception ex) when (ex is TaskCanceledException or OperationCanceledException)