From f724230c8b412ed56de3e4878a74c44420c394d9 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 19 Apr 2026 10:46:31 +0000 Subject: [PATCH 1/7] Initial plan From 7ac98527a995dfdec46293beacb2fb35afe7366e Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 19 Apr 2026 11:32:51 +0000 Subject: [PATCH 2/7] Fix StartAndForget flaky running-process assertion Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/c84ad3a6-2269-49a1-be61-284e675daa50 Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com> --- .../tests/StartAndForget.cs | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/src/libraries/System.Diagnostics.Process/tests/StartAndForget.cs b/src/libraries/System.Diagnostics.Process/tests/StartAndForget.cs index 0a3d26ec319365..68fbdb185fb549 100644 --- a/src/libraries/System.Diagnostics.Process/tests/StartAndForget.cs +++ b/src/libraries/System.Diagnostics.Process/tests/StartAndForget.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.IO; +using System.Runtime.InteropServices; using Microsoft.DotNet.RemoteExecutor; using Microsoft.Win32.SafeHandles; using Xunit; @@ -23,15 +24,10 @@ public void StartAndForget_StartsProcessAndReturnsValidPid(bool useProcessStartI Assert.True(pid > 0); using Process launched = Process.GetProcessById(pid); - try - { - Assert.False(launched.HasExited); - } - finally - { - launched.Kill(); - launched.WaitForExit(); - } +#pragma warning disable CA1416 // SIGKILL is supported on all platforms for SafeProcessHandle.Signal. + Assert.True(launched.SafeHandle.Signal(PosixSignal.SIGKILL)); +#pragma warning restore CA1416 + Assert.True(launched.WaitForExit(WaitInMS)); } [ConditionalFact(typeof(RemoteExecutor), nameof(RemoteExecutor.IsSupported))] From f45043a118ee45c32c1950073c323d4b746fbd23 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 19 Apr 2026 11:37:14 +0000 Subject: [PATCH 3/7] Harden StartAndForget test cleanup after SIGKILL assertion Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/c84ad3a6-2269-49a1-be61-284e675daa50 Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com> --- .../tests/StartAndForget.cs | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/libraries/System.Diagnostics.Process/tests/StartAndForget.cs b/src/libraries/System.Diagnostics.Process/tests/StartAndForget.cs index 68fbdb185fb549..f7bee6451714e7 100644 --- a/src/libraries/System.Diagnostics.Process/tests/StartAndForget.cs +++ b/src/libraries/System.Diagnostics.Process/tests/StartAndForget.cs @@ -25,9 +25,17 @@ public void StartAndForget_StartsProcessAndReturnsValidPid(bool useProcessStartI using Process launched = Process.GetProcessById(pid); #pragma warning disable CA1416 // SIGKILL is supported on all platforms for SafeProcessHandle.Signal. - Assert.True(launched.SafeHandle.Signal(PosixSignal.SIGKILL)); + try + { + Assert.True(launched.SafeHandle.Signal(PosixSignal.SIGKILL)); + Assert.True(launched.WaitForExit(WaitInMS)); + } + finally + { + launched.SafeHandle.Signal(PosixSignal.SIGKILL); + launched.WaitForExit(WaitInMS); + } #pragma warning restore CA1416 - Assert.True(launched.WaitForExit(WaitInMS)); } [ConditionalFact(typeof(RemoteExecutor), nameof(RemoteExecutor.IsSupported))] From b4ecac2aadcc47949727bb7dbaa1681efd81c151 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 19 Apr 2026 12:19:18 +0000 Subject: [PATCH 4/7] Address StartAndForget review feedback on pragma scope and cleanup Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/10d359fd-34fe-4733-b49c-ea5c0be6bc42 Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com> --- .../System.Diagnostics.Process/tests/StartAndForget.cs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/libraries/System.Diagnostics.Process/tests/StartAndForget.cs b/src/libraries/System.Diagnostics.Process/tests/StartAndForget.cs index f7bee6451714e7..57c239513b7a83 100644 --- a/src/libraries/System.Diagnostics.Process/tests/StartAndForget.cs +++ b/src/libraries/System.Diagnostics.Process/tests/StartAndForget.cs @@ -24,18 +24,17 @@ public void StartAndForget_StartsProcessAndReturnsValidPid(bool useProcessStartI Assert.True(pid > 0); using Process launched = Process.GetProcessById(pid); -#pragma warning disable CA1416 // SIGKILL is supported on all platforms for SafeProcessHandle.Signal. try { +#pragma warning disable CA1416 // SIGKILL is supported on all platforms for SafeProcessHandle.Signal. Assert.True(launched.SafeHandle.Signal(PosixSignal.SIGKILL)); +#pragma warning restore CA1416 Assert.True(launched.WaitForExit(WaitInMS)); } finally { - launched.SafeHandle.Signal(PosixSignal.SIGKILL); launched.WaitForExit(WaitInMS); } -#pragma warning restore CA1416 } [ConditionalFact(typeof(RemoteExecutor), nameof(RemoteExecutor.IsSupported))] From 459efcfb9805d431cd505efff487ff9e6af50c77 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 19 Apr 2026 20:52:46 +0000 Subject: [PATCH 5/7] Revert StartAndForget workaround and map arguments for StartAndForget overload Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/9daf3d53-7bbd-4624-ab86-d92ca763b757 Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com> --- .../tests/StartAndForget.cs | 56 ++++++++++++++++--- 1 file changed, 49 insertions(+), 7 deletions(-) diff --git a/src/libraries/System.Diagnostics.Process/tests/StartAndForget.cs b/src/libraries/System.Diagnostics.Process/tests/StartAndForget.cs index 57c239513b7a83..8fff505dfa88ab 100644 --- a/src/libraries/System.Diagnostics.Process/tests/StartAndForget.cs +++ b/src/libraries/System.Diagnostics.Process/tests/StartAndForget.cs @@ -1,8 +1,9 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Collections.Generic; using System.IO; -using System.Runtime.InteropServices; +using System.Text; using Microsoft.DotNet.RemoteExecutor; using Microsoft.Win32.SafeHandles; using Xunit; @@ -17,23 +18,22 @@ public class StartAndForgetTests : ProcessTestBase public void StartAndForget_StartsProcessAndReturnsValidPid(bool useProcessStartInfo) { using Process template = CreateSleepProcess((int)TimeSpan.FromHours(1).TotalMilliseconds); + List? arguments = MapToArgumentList(template.StartInfo); int pid = useProcessStartInfo ? Process.StartAndForget(template.StartInfo) - : Process.StartAndForget(template.StartInfo.FileName, template.StartInfo.ArgumentList); + : Process.StartAndForget(template.StartInfo.FileName, arguments); Assert.True(pid > 0); using Process launched = Process.GetProcessById(pid); try { -#pragma warning disable CA1416 // SIGKILL is supported on all platforms for SafeProcessHandle.Signal. - Assert.True(launched.SafeHandle.Signal(PosixSignal.SIGKILL)); -#pragma warning restore CA1416 - Assert.True(launched.WaitForExit(WaitInMS)); + Assert.False(launched.HasExited); } finally { - launched.WaitForExit(WaitInMS); + launched.Kill(); + launched.WaitForExit(); } } @@ -113,5 +113,47 @@ public void StartAndForget_WithUseShellExecute_ThrowsInvalidOperationException() Assert.Throws(() => Process.StartAndForget(startInfo)); } + + private static List? MapToArgumentList(ProcessStartInfo startInfo) + { + string arguments = startInfo.Arguments; + if (string.IsNullOrEmpty(arguments)) + { + return null; + } + + List list = new(); + StringBuilder builder = new(); + bool isQuoted = false; + + foreach (char c in arguments) + { + switch (c) + { + case '"' when !isQuoted: + isQuoted = true; + break; + case ' ' when !isQuoted: + case '"' when isQuoted: + if (builder.Length > 0) + { + list.Add(builder.ToString()); + builder.Clear(); + } + isQuoted = false; + break; + default: + builder.Append(c); + break; + } + } + + if (builder.Length > 0) + { + list.Add(builder.ToString()); + } + + return list; + } } } From db98b20efccfcc1168f3d841cb043e3b172c100c Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 20 Apr 2026 16:14:04 +0000 Subject: [PATCH 6/7] Inline StartAndForget argument mapping call in false branch Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/1762a9d2-5f02-4434-abcf-19188faf5214 Co-authored-by: jkotas <6668460+jkotas@users.noreply.github.com> --- .../System.Diagnostics.Process/tests/StartAndForget.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/libraries/System.Diagnostics.Process/tests/StartAndForget.cs b/src/libraries/System.Diagnostics.Process/tests/StartAndForget.cs index 8fff505dfa88ab..5a7381f5058ed0 100644 --- a/src/libraries/System.Diagnostics.Process/tests/StartAndForget.cs +++ b/src/libraries/System.Diagnostics.Process/tests/StartAndForget.cs @@ -18,10 +18,9 @@ public class StartAndForgetTests : ProcessTestBase public void StartAndForget_StartsProcessAndReturnsValidPid(bool useProcessStartInfo) { using Process template = CreateSleepProcess((int)TimeSpan.FromHours(1).TotalMilliseconds); - List? arguments = MapToArgumentList(template.StartInfo); int pid = useProcessStartInfo ? Process.StartAndForget(template.StartInfo) - : Process.StartAndForget(template.StartInfo.FileName, arguments); + : Process.StartAndForget(template.StartInfo.FileName, MapToArgumentList(template.StartInfo)); Assert.True(pid > 0); From 9ee27256c6f61d9dd9999f931fb54ed2c4add764 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 20 Apr 2026 16:54:23 +0000 Subject: [PATCH 7/7] Add explanation comment for MapToArgumentList helper Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/06fbf653-1bca-4454-9808-3281ddb2b7aa Co-authored-by: jkotas <6668460+jkotas@users.noreply.github.com> --- .../System.Diagnostics.Process/tests/StartAndForget.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/libraries/System.Diagnostics.Process/tests/StartAndForget.cs b/src/libraries/System.Diagnostics.Process/tests/StartAndForget.cs index 5a7381f5058ed0..dc20e3fd9a8a45 100644 --- a/src/libraries/System.Diagnostics.Process/tests/StartAndForget.cs +++ b/src/libraries/System.Diagnostics.Process/tests/StartAndForget.cs @@ -113,6 +113,8 @@ public void StartAndForget_WithUseShellExecute_ThrowsInvalidOperationException() Assert.Throws(() => Process.StartAndForget(startInfo)); } + // RemoteExecutor populates ProcessStartInfo.Arguments, but StartAndForget(fileName, arguments) + // takes an argument list, so this helper maps the serialized argument string for this test. private static List? MapToArgumentList(ProcessStartInfo startInfo) { string arguments = startInfo.Arguments;