Skip to content
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 @@ -622,18 +622,18 @@ internal static void CheckChildren(bool reapAll, bool configureConsole)
pid = Interop.Sys.WaitIdAnyExitedNoHangNoWait();
if (pid > 0)
{
if (s_childProcessWaitStates.TryGetValue(pid, out ProcessWaitState? pws))
if (s_childProcessWaitStates.TryGetValue(pid, out ProcessWaitState? pws) &&
pws.TryReapChild(configureConsole))
Comment thread
adamsitnik marked this conversation as resolved.
{
// Known Process.
if (pws.TryReapChild(configureConsole))
{
pws.ReleaseRef();
}
pws.ReleaseRef();
}
else
{
// unlikely: This is not a managed Process, so we are not responsible for reaping.
// Fall back to checking all Processes.
// The child may be unmanaged, or stopped rather than exited. On macOS,
// waitid can report stopped children despite omitting WSTOPPED;
// the SIGCHLD handler is also registered with SA_NOCLDSTOP.
// Scan all managed children instead of repeatedly observing
// the same child without reaping it.
checkAll = true;
break;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,4 @@

using Xunit;

#if TARGET_OSX
// Retain serialization until process-management hangs under concurrent test classes on macOS are resolved.
// https://github.com/dotnet/runtime/issues/135294
[assembly: CollectionBehavior(CollectionBehavior.CollectionPerAssembly)]
#endif

[assembly: SkipOnPlatform(TestPlatforms.Browser, "System.Diagnostics.Process is not supported on Browser.")]
Original file line number Diff line number Diff line change
Expand Up @@ -769,6 +769,64 @@ public async Task TestChildProcessCleanupAfterDispose(bool shortProcess, bool en
Assert.True(processReaped);
}

[ConditionalTheory(typeof(RemoteExecutor), nameof(RemoteExecutor.IsSupported))]
[PlatformSpecific(TestPlatforms.OSX)]
[InlineData(false)]
[InlineData(true)]
public void WaitForExit_StoppedChild_DoesNotPreventReapingOtherChildren(bool useAsync)
Comment thread
adamsitnik marked this conversation as resolved.
{
RemoteExecutor.Invoke(async useAsyncString =>
{
const uint StoppedProcessStatus = 4; // SSTOP in sys/proc.h.
using Process stopped = Process.Start("/bin/sleep", "300");
using Process exiting = Process.Start("/bin/sleep", "300");
int stoppedPid = stopped.Id;
int exitingPid = exiting.Id;
int killSignal = Interop.Sys.GetPlatformSignalNumber(PosixSignal.SIGKILL);
using var sigChildReceived = new ManualResetEventSlim();
using PosixSignalRegistration registration = PosixSignalRegistration.Create(PosixSignal.SIGCHLD, context =>
{
context.Cancel = true;
sigChildReceived.Set();
});

try
{
Assert.Equal(0, Interop.Sys.Kill(stoppedPid, Interop.Sys.GetPlatformSIGSTOP()));
Comment thread
adamsitnik marked this conversation as resolved.

Assert.True(SpinWait.SpinUntil(
() => Interop.libproc.GetProcessInfoById(stoppedPid) is { } info &&
info.pbsd.pbi_status == StoppedProcessStatus, WaitInMS));

sigChildReceived.Reset();
Assert.Equal(0, Interop.Sys.Kill(Environment.ProcessId, Interop.Sys.GetPlatformSignalNumber(PosixSignal.SIGCHLD)));
Assert.True(sigChildReceived.Wait(WaitInMS));

Assert.Equal(0, Interop.Sys.Kill(exitingPid, killSignal));
if (bool.Parse(useAsyncString))
{
using var cts = new CancellationTokenSource(WaitInMS);
await exiting.WaitForExitAsync(cts.Token);
}
else
{
Assert.True(exiting.WaitForExit(WaitInMS));
}
Assert.True(exiting.HasExited);
}
finally
{
// Bypass managed process locks so cleanup also works if the reaper is stuck.
Assert.Equal(0, Interop.Sys.Kill(stoppedPid, killSignal));
Assert.True(stopped.WaitForExit(WaitInMS));
exiting.Kill();
Assert.True(exiting.WaitForExit(WaitInMS));
}

return RemoteExecutor.SuccessExitCode;
}, useAsync.ToString()).Dispose();
}

private static Process CreateShortProcess()
{
Process process = new Process();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
<PropertyGroup>
<TargetPlatformIdentifier>$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)'))</TargetPlatformIdentifier>
<DefineConstants Condition="'$(TargetPlatformIdentifier)' == 'windows'">$(DefineConstants);TargetsWindows</DefineConstants>
<DefineConstants Condition="'$(TargetOS)' == 'osx' and '$(TargetPlatformIdentifier)' == 'unix'">$(DefineConstants);TARGET_OSX</DefineConstants>
</PropertyGroup>
<ItemGroup>
<Compile Include="$(CommonPath)System\IO\StringParser.cs"
Expand Down Expand Up @@ -93,6 +92,8 @@
Link="Common\Interop\OSX\Interop.Libraries.cs" />
<Compile Include="$(CommonPath)Interop\OSX\Interop.libproc.cs"
Link="Common\Interop\OSX\Interop.libproc.cs" />
<Compile Include="$(CommonPath)Interop\OSX\Interop.libproc.GetProcessInfoById.cs"
Link="Common\Interop\OSX\Interop.libproc.GetProcessInfoById.cs" />
<Compile Include="$(CommonPath)Interop\OSX\Interop.libSystem.cs"
Link="Common\Interop\OSX\Interop.libSystem.cs" />
<Compile Include="$(CommonPath)Interop\Unix\Interop.Libraries.cs"
Expand Down
Loading