From ffc7fea1cc78177906e55c1f0b49d63080c7896d Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 22 Mar 2026 04:59:37 +0000 Subject: [PATCH 01/17] Initial plan From 34a4c13a057475a054e5b3de3bd1df32ff881435 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 22 Mar 2026 05:03:57 +0000 Subject: [PATCH 02/17] Remove retry loop workaround for process kill in CollectCrashDumpWithCreateDump Co-authored-by: danmoseley <6385855+danmoseley@users.noreply.github.com> Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/a2dbb77d-4221-4987-8406-2d2f97adfeb8 --- .../CoreCLRTestLibrary/CoreclrTestWrapperLib.cs | 17 +---------------- 1 file changed, 1 insertion(+), 16 deletions(-) diff --git a/src/tests/Common/CoreCLRTestLibrary/CoreclrTestWrapperLib.cs b/src/tests/Common/CoreCLRTestLibrary/CoreclrTestWrapperLib.cs index d09282fc976844..2c75213380bb9a 100644 --- a/src/tests/Common/CoreCLRTestLibrary/CoreclrTestWrapperLib.cs +++ b/src/tests/Common/CoreCLRTestLibrary/CoreclrTestWrapperLib.cs @@ -354,22 +354,7 @@ static bool CollectCrashDumpWithCreateDump(Process process, string crashDumpPath } else { - // Workaround for https://github.com/dotnet/runtime/issues/93321 - const int MaxRetries = 5; - for (int i = 0; i < MaxRetries; i++) - { - try - { - createdump.Kill(entireProcessTree: true); - break; - } - catch (Exception e) when (i < MaxRetries - 1) - { - Console.WriteLine($"Process.Kill(entireProcessTree: true) failed:"); - Console.WriteLine(e); - Console.WriteLine("Retrying..."); - } - } + createdump.Kill(entireProcessTree: true); } return fSuccess && createdump.ExitCode == 0; From a1b48fef34922f70d23c7a01c7d9fe032dcbd3a2 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 22 Mar 2026 05:18:46 +0000 Subject: [PATCH 03/17] Fix EPERM when killing sudo-launched createdump by using sudo kill instead of Process.Kill Co-authored-by: danmoseley <6385855+danmoseley@users.noreply.github.com> Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/70211a86-2150-4fc8-9869-b914448a0643 --- .../CoreclrTestWrapperLib.cs | 41 ++++++++++++++++++- 1 file changed, 40 insertions(+), 1 deletion(-) diff --git a/src/tests/Common/CoreCLRTestLibrary/CoreclrTestWrapperLib.cs b/src/tests/Common/CoreCLRTestLibrary/CoreclrTestWrapperLib.cs index 2c75213380bb9a..913f53efc183ae 100644 --- a/src/tests/Common/CoreCLRTestLibrary/CoreclrTestWrapperLib.cs +++ b/src/tests/Common/CoreCLRTestLibrary/CoreclrTestWrapperLib.cs @@ -294,6 +294,42 @@ static bool CollectCrashDumpWithMiniDumpWriteDump(Process process, string crashD return collectedDump; } + // Kills a process tree rooted at the given process using 'sudo kill -9', + // which is required when the processes run as root (e.g. launched via 'sudo'). + static void KillProcessTreeWithSudo(Process process) + { + // Kill children first (depth-first), then the process itself. + try + { + foreach (Process child in process.GetChildren()) + { + KillProcessTreeWithSudo(child); + child.Dispose(); + } + } + catch + { + // Process may have already exited. + } + + if (process.TryGetProcessId(out int pid)) + { + using Process sudoKill = new Process(); + sudoKill.StartInfo.FileName = "sudo"; + sudoKill.StartInfo.Arguments = $"kill -9 {pid}"; + sudoKill.StartInfo.UseShellExecute = false; + try + { + sudoKill.Start(); + sudoKill.WaitForExit(30_000); + } + catch + { + // Best effort — process may have already exited. + } + } + } + static bool CollectCrashDumpWithCreateDump(Process process, string crashDumpPath, StreamWriter outputWriter) { string? coreRoot = Environment.GetEnvironmentVariable("CORE_ROOT"); @@ -354,7 +390,10 @@ static bool CollectCrashDumpWithCreateDump(Process process, string crashDumpPath } else { - createdump.Kill(entireProcessTree: true); + // createdump was launched via 'sudo', so the process and its children run as root. + // We cannot send SIGKILL to root-owned processes from a non-root process (EPERM). + // Use 'sudo kill' to terminate the timed-out process tree. + KillProcessTreeWithSudo(createdump); } return fSuccess && createdump.ExitCode == 0; From 85f204af21d28f60d2908e935f5ddb93244e5200 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 22 Mar 2026 05:46:44 +0000 Subject: [PATCH 04/17] Address review feedback: add logging, reduce kill timeout, note race condition Co-authored-by: danmoseley <6385855+danmoseley@users.noreply.github.com> Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/d515aa14-bc39-4049-80be-7464fad96cf5 --- .../CoreCLRTestLibrary/CoreclrTestWrapperLib.cs | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/src/tests/Common/CoreCLRTestLibrary/CoreclrTestWrapperLib.cs b/src/tests/Common/CoreCLRTestLibrary/CoreclrTestWrapperLib.cs index 913f53efc183ae..c24565b212cf1e 100644 --- a/src/tests/Common/CoreCLRTestLibrary/CoreclrTestWrapperLib.cs +++ b/src/tests/Common/CoreCLRTestLibrary/CoreclrTestWrapperLib.cs @@ -296,6 +296,8 @@ static bool CollectCrashDumpWithMiniDumpWriteDump(Process process, string crashD // Kills a process tree rooted at the given process using 'sudo kill -9', // which is required when the processes run as root (e.g. launched via 'sudo'). + // Note: there is an inherent race where new children could be spawned after GetChildren + // is called, but createdump is not expected to spawn children after startup. static void KillProcessTreeWithSudo(Process process) { // Kill children first (depth-first), then the process itself. @@ -307,9 +309,10 @@ static void KillProcessTreeWithSudo(Process process) child.Dispose(); } } - catch + catch (Exception e) { - // Process may have already exited. + // Process may have already exited, or enumeration failed. + Console.WriteLine($"KillProcessTreeWithSudo: exception enumerating children (process may have exited): {e}"); } if (process.TryGetProcessId(out int pid)) @@ -321,11 +324,12 @@ static void KillProcessTreeWithSudo(Process process) try { sudoKill.Start(); - sudoKill.WaitForExit(30_000); + // A kill -9 should complete almost immediately; use a short timeout. + sudoKill.WaitForExit(5_000); } - catch + catch (Exception e) { - // Best effort — process may have already exited. + Console.WriteLine($"KillProcessTreeWithSudo: exception killing pid {pid}: {e}"); } } } From 3bc6a0aba3a3bc6463baccacc88f8ff010bd1c48 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 22 Mar 2026 07:33:23 +0000 Subject: [PATCH 05/17] Address reviewer feedback: sudo -n, redirect output, check WaitForExit result and exit code Co-authored-by: danmoseley <6385855+danmoseley@users.noreply.github.com> Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/e8f15f3b-2e32-4815-b8f3-3659fd3dc034 --- .../CoreclrTestWrapperLib.cs | 35 +++++++++++++++++-- 1 file changed, 33 insertions(+), 2 deletions(-) diff --git a/src/tests/Common/CoreCLRTestLibrary/CoreclrTestWrapperLib.cs b/src/tests/Common/CoreCLRTestLibrary/CoreclrTestWrapperLib.cs index c24565b212cf1e..4029606fea0eb2 100644 --- a/src/tests/Common/CoreCLRTestLibrary/CoreclrTestWrapperLib.cs +++ b/src/tests/Common/CoreCLRTestLibrary/CoreclrTestWrapperLib.cs @@ -319,13 +319,44 @@ static void KillProcessTreeWithSudo(Process process) { using Process sudoKill = new Process(); sudoKill.StartInfo.FileName = "sudo"; - sudoKill.StartInfo.Arguments = $"kill -9 {pid}"; + // Use -n (non-interactive) so sudo fails fast instead of prompting if passwordless + // sudo is not configured, rather than hanging. + sudoKill.StartInfo.Arguments = $"-n kill -9 {pid}"; sudoKill.StartInfo.UseShellExecute = false; + sudoKill.StartInfo.RedirectStandardOutput = true; + sudoKill.StartInfo.RedirectStandardError = true; try { sudoKill.Start(); // A kill -9 should complete almost immediately; use a short timeout. - sudoKill.WaitForExit(5_000); + bool exited = sudoKill.WaitForExit(5_000); + if (!exited) + { + Console.WriteLine($"KillProcessTreeWithSudo: sudo kill -9 {pid} did not exit within timeout; terminating sudo process."); + try + { + sudoKill.Kill(entireProcessTree: true); + } + catch (Exception killEx) + { + Console.WriteLine($"KillProcessTreeWithSudo: exception terminating hung sudo process for pid {pid}: {killEx}"); + } + } + else if (sudoKill.ExitCode != 0) + { + string stdOut = string.Empty; + string stdErr = string.Empty; + try + { + stdOut = sudoKill.StandardOutput.ReadToEnd(); + stdErr = sudoKill.StandardError.ReadToEnd(); + } + catch (Exception ioEx) + { + Console.WriteLine($"KillProcessTreeWithSudo: exception reading sudo output for pid {pid}: {ioEx}"); + } + Console.WriteLine($"KillProcessTreeWithSudo: sudo kill -9 {pid} exited with code {sudoKill.ExitCode}. stdout: {stdOut} stderr: {stdErr}"); + } } catch (Exception e) { From b372187479d86c76536a4a5e37472f57d2e9ef92 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 22 Mar 2026 13:49:22 +0000 Subject: [PATCH 06/17] Remove child process handling from KillWithSudo; rename to KillWithSudo Co-authored-by: danmoseley <6385855+danmoseley@users.noreply.github.com> Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/c8cdc4b9-b63d-4135-9b05-b38af866fc03 --- .../CoreclrTestWrapperLib.cs | 35 +++++-------------- 1 file changed, 9 insertions(+), 26 deletions(-) diff --git a/src/tests/Common/CoreCLRTestLibrary/CoreclrTestWrapperLib.cs b/src/tests/Common/CoreCLRTestLibrary/CoreclrTestWrapperLib.cs index 4029606fea0eb2..531439653a49e5 100644 --- a/src/tests/Common/CoreCLRTestLibrary/CoreclrTestWrapperLib.cs +++ b/src/tests/Common/CoreCLRTestLibrary/CoreclrTestWrapperLib.cs @@ -294,27 +294,10 @@ static bool CollectCrashDumpWithMiniDumpWriteDump(Process process, string crashD return collectedDump; } - // Kills a process tree rooted at the given process using 'sudo kill -9', - // which is required when the processes run as root (e.g. launched via 'sudo'). - // Note: there is an inherent race where new children could be spawned after GetChildren - // is called, but createdump is not expected to spawn children after startup. - static void KillProcessTreeWithSudo(Process process) + // Kills the given process using 'sudo kill -9', which is required when the process runs + // as root (e.g. launched via 'sudo') and cannot be killed by a non-root process (EPERM). + static void KillWithSudo(Process process) { - // Kill children first (depth-first), then the process itself. - try - { - foreach (Process child in process.GetChildren()) - { - KillProcessTreeWithSudo(child); - child.Dispose(); - } - } - catch (Exception e) - { - // Process may have already exited, or enumeration failed. - Console.WriteLine($"KillProcessTreeWithSudo: exception enumerating children (process may have exited): {e}"); - } - if (process.TryGetProcessId(out int pid)) { using Process sudoKill = new Process(); @@ -332,14 +315,14 @@ static void KillProcessTreeWithSudo(Process process) bool exited = sudoKill.WaitForExit(5_000); if (!exited) { - Console.WriteLine($"KillProcessTreeWithSudo: sudo kill -9 {pid} did not exit within timeout; terminating sudo process."); + Console.WriteLine($"KillWithSudo: sudo kill -9 {pid} did not exit within timeout; terminating sudo process."); try { sudoKill.Kill(entireProcessTree: true); } catch (Exception killEx) { - Console.WriteLine($"KillProcessTreeWithSudo: exception terminating hung sudo process for pid {pid}: {killEx}"); + Console.WriteLine($"KillWithSudo: exception terminating hung sudo process for pid {pid}: {killEx}"); } } else if (sudoKill.ExitCode != 0) @@ -353,14 +336,14 @@ static void KillProcessTreeWithSudo(Process process) } catch (Exception ioEx) { - Console.WriteLine($"KillProcessTreeWithSudo: exception reading sudo output for pid {pid}: {ioEx}"); + Console.WriteLine($"KillWithSudo: exception reading sudo output for pid {pid}: {ioEx}"); } - Console.WriteLine($"KillProcessTreeWithSudo: sudo kill -9 {pid} exited with code {sudoKill.ExitCode}. stdout: {stdOut} stderr: {stdErr}"); + Console.WriteLine($"KillWithSudo: sudo kill -9 {pid} exited with code {sudoKill.ExitCode}. stdout: {stdOut} stderr: {stdErr}"); } } catch (Exception e) { - Console.WriteLine($"KillProcessTreeWithSudo: exception killing pid {pid}: {e}"); + Console.WriteLine($"KillWithSudo: exception killing pid {pid}: {e}"); } } } @@ -428,7 +411,7 @@ static bool CollectCrashDumpWithCreateDump(Process process, string crashDumpPath // createdump was launched via 'sudo', so the process and its children run as root. // We cannot send SIGKILL to root-owned processes from a non-root process (EPERM). // Use 'sudo kill' to terminate the timed-out process tree. - KillProcessTreeWithSudo(createdump); + KillWithSudo(createdump); } return fSuccess && createdump.ExitCode == 0; From 31b1824be36adbfd2954b66db11baa6b64bf92d2 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 22 Mar 2026 13:59:29 +0000 Subject: [PATCH 07/17] Read stdout/stderr async before WaitForExit to avoid pipe buffer deadlock Co-authored-by: danmoseley <6385855+danmoseley@users.noreply.github.com> Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/25443ae6-f4aa-4203-a256-bc6674ea3c68 --- .../Common/CoreCLRTestLibrary/CoreclrTestWrapperLib.cs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/tests/Common/CoreCLRTestLibrary/CoreclrTestWrapperLib.cs b/src/tests/Common/CoreCLRTestLibrary/CoreclrTestWrapperLib.cs index 531439653a49e5..a194f5c343a8b2 100644 --- a/src/tests/Common/CoreCLRTestLibrary/CoreclrTestWrapperLib.cs +++ b/src/tests/Common/CoreCLRTestLibrary/CoreclrTestWrapperLib.cs @@ -311,6 +311,9 @@ static void KillWithSudo(Process process) try { sudoKill.Start(); + // Read stdout/stderr asynchronously to avoid deadlock if the process fills the pipe buffer. + System.Threading.Tasks.Task stdOutTask = sudoKill.StandardOutput.ReadToEndAsync(); + System.Threading.Tasks.Task stdErrTask = sudoKill.StandardError.ReadToEndAsync(); // A kill -9 should complete almost immediately; use a short timeout. bool exited = sudoKill.WaitForExit(5_000); if (!exited) @@ -331,8 +334,8 @@ static void KillWithSudo(Process process) string stdErr = string.Empty; try { - stdOut = sudoKill.StandardOutput.ReadToEnd(); - stdErr = sudoKill.StandardError.ReadToEnd(); + stdOut = stdOutTask.Result; + stdErr = stdErrTask.Result; } catch (Exception ioEx) { From 2699eaf1792e1491b71b5a58924cf8856c234f46 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 22 Mar 2026 15:48:57 +0000 Subject: [PATCH 08/17] Clean up KillWithSudo: ProcessStartInfo initializer, var for tasks, GetAwaiter().GetResult() Co-authored-by: danmoseley <6385855+danmoseley@users.noreply.github.com> Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/ad8e68e0-a906-4bf3-aff5-234921ff4543 --- .../CoreclrTestWrapperLib.cs | 28 ++++++++++--------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/src/tests/Common/CoreCLRTestLibrary/CoreclrTestWrapperLib.cs b/src/tests/Common/CoreCLRTestLibrary/CoreclrTestWrapperLib.cs index a194f5c343a8b2..f36528267e3f00 100644 --- a/src/tests/Common/CoreCLRTestLibrary/CoreclrTestWrapperLib.cs +++ b/src/tests/Common/CoreCLRTestLibrary/CoreclrTestWrapperLib.cs @@ -300,20 +300,22 @@ static void KillWithSudo(Process process) { if (process.TryGetProcessId(out int pid)) { - using Process sudoKill = new Process(); - sudoKill.StartInfo.FileName = "sudo"; - // Use -n (non-interactive) so sudo fails fast instead of prompting if passwordless - // sudo is not configured, rather than hanging. - sudoKill.StartInfo.Arguments = $"-n kill -9 {pid}"; - sudoKill.StartInfo.UseShellExecute = false; - sudoKill.StartInfo.RedirectStandardOutput = true; - sudoKill.StartInfo.RedirectStandardError = true; + using Process sudoKill = new Process + { + StartInfo = new ProcessStartInfo + { + FileName = "sudo", + Arguments = $"-n kill -9 {pid}", + UseShellExecute = false, + RedirectStandardOutput = true, + RedirectStandardError = true, + } + }; try { sudoKill.Start(); - // Read stdout/stderr asynchronously to avoid deadlock if the process fills the pipe buffer. - System.Threading.Tasks.Task stdOutTask = sudoKill.StandardOutput.ReadToEndAsync(); - System.Threading.Tasks.Task stdErrTask = sudoKill.StandardError.ReadToEndAsync(); + var stdOutTask = sudoKill.StandardOutput.ReadToEndAsync(); + var stdErrTask = sudoKill.StandardError.ReadToEndAsync(); // A kill -9 should complete almost immediately; use a short timeout. bool exited = sudoKill.WaitForExit(5_000); if (!exited) @@ -334,8 +336,8 @@ static void KillWithSudo(Process process) string stdErr = string.Empty; try { - stdOut = stdOutTask.Result; - stdErr = stdErrTask.Result; + stdOut = stdOutTask.GetAwaiter().GetResult(); + stdErr = stdErrTask.GetAwaiter().GetResult(); } catch (Exception ioEx) { From da1e14535fbb5e6fc047aaf7adffcdcf4a7a71cd Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 22 Mar 2026 16:02:12 +0000 Subject: [PATCH 09/17] Remove unnecessary UseShellExecute = false (defaults to false in .NET Core) Co-authored-by: jkotas <6668460+jkotas@users.noreply.github.com> Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/9698ae1c-8ae1-46ca-bded-ad865c922bda --- src/tests/Common/CoreCLRTestLibrary/CoreclrTestWrapperLib.cs | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/tests/Common/CoreCLRTestLibrary/CoreclrTestWrapperLib.cs b/src/tests/Common/CoreCLRTestLibrary/CoreclrTestWrapperLib.cs index f36528267e3f00..fa372901f7e03e 100644 --- a/src/tests/Common/CoreCLRTestLibrary/CoreclrTestWrapperLib.cs +++ b/src/tests/Common/CoreCLRTestLibrary/CoreclrTestWrapperLib.cs @@ -306,7 +306,6 @@ static void KillWithSudo(Process process) { FileName = "sudo", Arguments = $"-n kill -9 {pid}", - UseShellExecute = false, RedirectStandardOutput = true, RedirectStandardError = true, } @@ -367,7 +366,6 @@ static bool CollectCrashDumpWithCreateDump(Process process, string crashDumpPath createdump.StartInfo.FileName = "sudo"; createdump.StartInfo.Arguments = $"{createdumpPath} {arguments}"; - createdump.StartInfo.UseShellExecute = false; createdump.StartInfo.RedirectStandardOutput = true; createdump.StartInfo.RedirectStandardError = true; @@ -394,7 +392,6 @@ static bool CollectCrashDumpWithCreateDump(Process process, string crashDumpPath chown.StartInfo.FileName = "sudo"; chown.StartInfo.Arguments = $"chown \"{Environment.UserName}\" \"{crashDumpPath}\""; - chown.StartInfo.UseShellExecute = false; chown.StartInfo.RedirectStandardOutput = true; chown.StartInfo.RedirectStandardError = true; @@ -513,7 +510,6 @@ public int RunTest(string executable, string outputFile, string errorFile, strin process.StartInfo.Arguments = executable; } - process.StartInfo.UseShellExecute = false; process.StartInfo.RedirectStandardOutput = true; process.StartInfo.RedirectStandardError = true; process.StartInfo.EnvironmentVariables.Add("__Category", category); @@ -611,7 +607,6 @@ private static string GetAllProcessNames_wmic() process.StartInfo.FileName = "cmd.exe"; process.StartInfo.Arguments = $"/c {command}"; process.StartInfo.RedirectStandardOutput = true; - process.StartInfo.UseShellExecute = false; process.StartInfo.CreateNoWindow = true; // Start the process and read the output From ed8e78632fc547e7c14be7b24c9d0003708527fd Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 22 Mar 2026 16:30:34 +0000 Subject: [PATCH 10/17] Simplify KillWithSudo: propagate exceptions, use Task and Task.WaitAll+Result pattern Co-authored-by: danmoseley <6385855+danmoseley@users.noreply.github.com> Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/45ea84c6-64df-41ec-b3e2-d4183c266aaa --- .../CoreclrTestWrapperLib.cs | 49 ++++++------------- 1 file changed, 14 insertions(+), 35 deletions(-) diff --git a/src/tests/Common/CoreCLRTestLibrary/CoreclrTestWrapperLib.cs b/src/tests/Common/CoreCLRTestLibrary/CoreclrTestWrapperLib.cs index fa372901f7e03e..d482a993d54bc5 100644 --- a/src/tests/Common/CoreCLRTestLibrary/CoreclrTestWrapperLib.cs +++ b/src/tests/Common/CoreCLRTestLibrary/CoreclrTestWrapperLib.cs @@ -310,44 +310,23 @@ static void KillWithSudo(Process process) RedirectStandardError = true, } }; - try + sudoKill.Start(); + Task stdOutTask = sudoKill.StandardOutput.ReadToEndAsync(); + Task stdErrTask = sudoKill.StandardError.ReadToEndAsync(); + // A kill -9 should complete almost immediately; use a short timeout. + bool exited = sudoKill.WaitForExit(5_000); + if (!exited) { - sudoKill.Start(); - var stdOutTask = sudoKill.StandardOutput.ReadToEndAsync(); - var stdErrTask = sudoKill.StandardError.ReadToEndAsync(); - // A kill -9 should complete almost immediately; use a short timeout. - bool exited = sudoKill.WaitForExit(5_000); - if (!exited) - { - Console.WriteLine($"KillWithSudo: sudo kill -9 {pid} did not exit within timeout; terminating sudo process."); - try - { - sudoKill.Kill(entireProcessTree: true); - } - catch (Exception killEx) - { - Console.WriteLine($"KillWithSudo: exception terminating hung sudo process for pid {pid}: {killEx}"); - } - } - else if (sudoKill.ExitCode != 0) - { - string stdOut = string.Empty; - string stdErr = string.Empty; - try - { - stdOut = stdOutTask.GetAwaiter().GetResult(); - stdErr = stdErrTask.GetAwaiter().GetResult(); - } - catch (Exception ioEx) - { - Console.WriteLine($"KillWithSudo: exception reading sudo output for pid {pid}: {ioEx}"); - } - Console.WriteLine($"KillWithSudo: sudo kill -9 {pid} exited with code {sudoKill.ExitCode}. stdout: {stdOut} stderr: {stdErr}"); - } + Console.WriteLine($"KillWithSudo: sudo kill -9 {pid} did not exit within timeout; terminating sudo process."); + sudoKill.Kill(entireProcessTree: true); } - catch (Exception e) + else { - Console.WriteLine($"KillWithSudo: exception killing pid {pid}: {e}"); + Task.WaitAll(stdOutTask, stdErrTask); + if (sudoKill.ExitCode != 0) + { + Console.WriteLine($"KillWithSudo: sudo kill -9 {pid} exited with code {sudoKill.ExitCode}. stdout: {stdOutTask.Result} stderr: {stdErrTask.Result}"); + } } } } From 76cc8104da5bd0e76619a008e81ebe2e4d588665 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 22 Mar 2026 17:41:56 +0000 Subject: [PATCH 11/17] Address jkotas feedback: fix comment wording and newline log formatting Co-authored-by: jkotas <6668460+jkotas@users.noreply.github.com> Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/d53973f0-bc70-402b-a4d0-0cb1f90093cc --- src/tests/Common/CoreCLRTestLibrary/CoreclrTestWrapperLib.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/tests/Common/CoreCLRTestLibrary/CoreclrTestWrapperLib.cs b/src/tests/Common/CoreCLRTestLibrary/CoreclrTestWrapperLib.cs index d482a993d54bc5..4778fca268c364 100644 --- a/src/tests/Common/CoreCLRTestLibrary/CoreclrTestWrapperLib.cs +++ b/src/tests/Common/CoreCLRTestLibrary/CoreclrTestWrapperLib.cs @@ -295,7 +295,7 @@ static bool CollectCrashDumpWithMiniDumpWriteDump(Process process, string crashD } // Kills the given process using 'sudo kill -9', which is required when the process runs - // as root (e.g. launched via 'sudo') and cannot be killed by a non-root process (EPERM). + // as root (e.g. launched via 'sudo') and cannot be killed by a non-root process. static void KillWithSudo(Process process) { if (process.TryGetProcessId(out int pid)) @@ -325,7 +325,7 @@ static void KillWithSudo(Process process) Task.WaitAll(stdOutTask, stdErrTask); if (sudoKill.ExitCode != 0) { - Console.WriteLine($"KillWithSudo: sudo kill -9 {pid} exited with code {sudoKill.ExitCode}. stdout: {stdOutTask.Result} stderr: {stdErrTask.Result}"); + Console.WriteLine($"KillWithSudo: sudo kill -9 {pid} exited with code {sudoKill.ExitCode}.{Environment.NewLine}stdout: {stdOutTask.Result}{Environment.NewLine}stderr: {stdErrTask.Result}"); } } } From c843e7c71a95aa14155393750d16968695dab7ce Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 22 Mar 2026 17:51:30 +0000 Subject: [PATCH 12/17] Split diagnostic Console.WriteLine into 3 separate statements Co-authored-by: jkotas <6668460+jkotas@users.noreply.github.com> Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/0070e5df-2424-4d00-b35e-824e9c9cdfcd --- src/tests/Common/CoreCLRTestLibrary/CoreclrTestWrapperLib.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/tests/Common/CoreCLRTestLibrary/CoreclrTestWrapperLib.cs b/src/tests/Common/CoreCLRTestLibrary/CoreclrTestWrapperLib.cs index 4778fca268c364..49f0a2532dad24 100644 --- a/src/tests/Common/CoreCLRTestLibrary/CoreclrTestWrapperLib.cs +++ b/src/tests/Common/CoreCLRTestLibrary/CoreclrTestWrapperLib.cs @@ -325,7 +325,9 @@ static void KillWithSudo(Process process) Task.WaitAll(stdOutTask, stdErrTask); if (sudoKill.ExitCode != 0) { - Console.WriteLine($"KillWithSudo: sudo kill -9 {pid} exited with code {sudoKill.ExitCode}.{Environment.NewLine}stdout: {stdOutTask.Result}{Environment.NewLine}stderr: {stdErrTask.Result}"); + Console.WriteLine($"KillWithSudo: sudo kill -9 {pid} exited with code {sudoKill.ExitCode}."); + Console.WriteLine($"stdout: {stdOutTask.Result}"); + Console.WriteLine($"stderr: {stdErrTask.Result}"); } } } From 84153abdb8444ac9c91830ec47ea16b28fc992ed Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 22 Mar 2026 17:56:51 +0000 Subject: [PATCH 13/17] Fix EPERM in timeout path: use Kill() not Kill(entireProcessTree: true) for sudoKill Co-authored-by: jkotas <6668460+jkotas@users.noreply.github.com> Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/841650d4-6146-47f2-b7fb-763a292fd331 --- src/tests/Common/CoreCLRTestLibrary/CoreclrTestWrapperLib.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tests/Common/CoreCLRTestLibrary/CoreclrTestWrapperLib.cs b/src/tests/Common/CoreCLRTestLibrary/CoreclrTestWrapperLib.cs index 49f0a2532dad24..288c71ae8c0369 100644 --- a/src/tests/Common/CoreCLRTestLibrary/CoreclrTestWrapperLib.cs +++ b/src/tests/Common/CoreCLRTestLibrary/CoreclrTestWrapperLib.cs @@ -318,7 +318,7 @@ static void KillWithSudo(Process process) if (!exited) { Console.WriteLine($"KillWithSudo: sudo kill -9 {pid} did not exit within timeout; terminating sudo process."); - sudoKill.Kill(entireProcessTree: true); + sudoKill.Kill(); } else { From 391136cc946c46bc88c85c29fb19cddfd872499c Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 22 Mar 2026 18:12:57 +0000 Subject: [PATCH 14/17] Remove timeout/kill logic for sudoKill per reviewer feedback Co-authored-by: jkotas <6668460+jkotas@users.noreply.github.com> Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/dee1a687-e44d-4551-bf84-6cdb1cebec8d --- .../CoreclrTestWrapperLib.cs | 21 ++++++------------- 1 file changed, 6 insertions(+), 15 deletions(-) diff --git a/src/tests/Common/CoreCLRTestLibrary/CoreclrTestWrapperLib.cs b/src/tests/Common/CoreCLRTestLibrary/CoreclrTestWrapperLib.cs index 288c71ae8c0369..cfb878d24869e0 100644 --- a/src/tests/Common/CoreCLRTestLibrary/CoreclrTestWrapperLib.cs +++ b/src/tests/Common/CoreCLRTestLibrary/CoreclrTestWrapperLib.cs @@ -313,22 +313,13 @@ static void KillWithSudo(Process process) sudoKill.Start(); Task stdOutTask = sudoKill.StandardOutput.ReadToEndAsync(); Task stdErrTask = sudoKill.StandardError.ReadToEndAsync(); - // A kill -9 should complete almost immediately; use a short timeout. - bool exited = sudoKill.WaitForExit(5_000); - if (!exited) + sudoKill.WaitForExit(); + Task.WaitAll(stdOutTask, stdErrTask); + if (sudoKill.ExitCode != 0) { - Console.WriteLine($"KillWithSudo: sudo kill -9 {pid} did not exit within timeout; terminating sudo process."); - sudoKill.Kill(); - } - else - { - Task.WaitAll(stdOutTask, stdErrTask); - if (sudoKill.ExitCode != 0) - { - Console.WriteLine($"KillWithSudo: sudo kill -9 {pid} exited with code {sudoKill.ExitCode}."); - Console.WriteLine($"stdout: {stdOutTask.Result}"); - Console.WriteLine($"stderr: {stdErrTask.Result}"); - } + Console.WriteLine($"KillWithSudo: sudo kill -9 {pid} exited with code {sudoKill.ExitCode}."); + Console.WriteLine($"stdout: {stdOutTask.Result}"); + Console.WriteLine($"stderr: {stdErrTask.Result}"); } } } From a74fa0c99e25d6141b542189efb6badad64ae494 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 22 Mar 2026 18:34:03 +0000 Subject: [PATCH 15/17] Simplify KillWithSudo: don't redirect output, let it go to console directly Co-authored-by: jkotas <6668460+jkotas@users.noreply.github.com> Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/147ec28d-750a-4c2e-947e-a22335663c8a --- .../CoreCLRTestLibrary/CoreclrTestWrapperLib.cs | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/src/tests/Common/CoreCLRTestLibrary/CoreclrTestWrapperLib.cs b/src/tests/Common/CoreCLRTestLibrary/CoreclrTestWrapperLib.cs index cfb878d24869e0..959806010a7bee 100644 --- a/src/tests/Common/CoreCLRTestLibrary/CoreclrTestWrapperLib.cs +++ b/src/tests/Common/CoreCLRTestLibrary/CoreclrTestWrapperLib.cs @@ -306,21 +306,10 @@ static void KillWithSudo(Process process) { FileName = "sudo", Arguments = $"-n kill -9 {pid}", - RedirectStandardOutput = true, - RedirectStandardError = true, } }; sudoKill.Start(); - Task stdOutTask = sudoKill.StandardOutput.ReadToEndAsync(); - Task stdErrTask = sudoKill.StandardError.ReadToEndAsync(); sudoKill.WaitForExit(); - Task.WaitAll(stdOutTask, stdErrTask); - if (sudoKill.ExitCode != 0) - { - Console.WriteLine($"KillWithSudo: sudo kill -9 {pid} exited with code {sudoKill.ExitCode}."); - Console.WriteLine($"stdout: {stdOutTask.Result}"); - Console.WriteLine($"stderr: {stdErrTask.Result}"); - } } } From 53ac3a9772d1b6085d5ac7c1031eb763e49ad9d1 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 22 Mar 2026 18:40:58 +0000 Subject: [PATCH 16/17] Use Process.Start convenience overload in KillWithSudo Co-authored-by: jkotas <6668460+jkotas@users.noreply.github.com> Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/3b687777-2d3d-4874-95ea-d9662f946346 --- .../CoreCLRTestLibrary/CoreclrTestWrapperLib.cs | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/src/tests/Common/CoreCLRTestLibrary/CoreclrTestWrapperLib.cs b/src/tests/Common/CoreCLRTestLibrary/CoreclrTestWrapperLib.cs index 959806010a7bee..d6d4c8c0d5d229 100644 --- a/src/tests/Common/CoreCLRTestLibrary/CoreclrTestWrapperLib.cs +++ b/src/tests/Common/CoreCLRTestLibrary/CoreclrTestWrapperLib.cs @@ -300,16 +300,7 @@ static void KillWithSudo(Process process) { if (process.TryGetProcessId(out int pid)) { - using Process sudoKill = new Process - { - StartInfo = new ProcessStartInfo - { - FileName = "sudo", - Arguments = $"-n kill -9 {pid}", - } - }; - sudoKill.Start(); - sudoKill.WaitForExit(); + Process.Start("sudo", $"-n kill -9 {pid}")?.WaitForExit(); } } From b6204d9aec9ed478e2fb0345737e085ee63bc0ff Mon Sep 17 00:00:00 2001 From: Jan Kotas Date: Sun, 22 Mar 2026 11:54:05 -0700 Subject: [PATCH 17/17] Apply suggestion from @jkotas --- src/tests/Common/CoreCLRTestLibrary/CoreclrTestWrapperLib.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tests/Common/CoreCLRTestLibrary/CoreclrTestWrapperLib.cs b/src/tests/Common/CoreCLRTestLibrary/CoreclrTestWrapperLib.cs index d6d4c8c0d5d229..77d1465e351190 100644 --- a/src/tests/Common/CoreCLRTestLibrary/CoreclrTestWrapperLib.cs +++ b/src/tests/Common/CoreCLRTestLibrary/CoreclrTestWrapperLib.cs @@ -300,7 +300,7 @@ static void KillWithSudo(Process process) { if (process.TryGetProcessId(out int pid)) { - Process.Start("sudo", $"-n kill -9 {pid}")?.WaitForExit(); + Process.Start("sudo", $"-n kill -9 {pid}").WaitForExit(); } }