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
35 changes: 10 additions & 25 deletions Library/SafeChildProcessHandle.Unix.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,26 +20,15 @@ namespace Microsoft.Win32.SafeHandles;
public partial class SafeChildProcessHandle
{
internal const int NoPidFd = -1;
// Buffer for reading from exit pipe (reused to avoid allocations)
private static readonly byte[] s_exitPipeBuffer = new byte[1];

private readonly int _exitPipeFd;

private SafeChildProcessHandle(int pidfd, int pid, int exitPipeFd)
private SafeChildProcessHandle(int pidfd, int pid)
: this(existingHandle: (IntPtr)pidfd, ownsHandle: true)
{
ProcessId = pid;
_exitPipeFd = exitPipeFd;
}

protected override bool ReleaseHandle()
{
// Close the exit pipe fd if it's valid
if (_exitPipeFd > 0)
{
close(_exitPipeFd);
}

return (int)this.handle switch
{
NoPidFd => true,
Expand Down Expand Up @@ -116,7 +105,6 @@ private static unsafe SafeChildProcessHandle StartProcessInternal(string resolve
workingDirPtr,
out int pid,
out int pidfd,
out int exitPipeFd,
options.KillOnParentExit ? 1 : 0,
createSuspended ? 1 : 0,
options.CreateNewProcessGroup ? 1 : 0,
Expand All @@ -130,7 +118,7 @@ private static unsafe SafeChildProcessHandle StartProcessInternal(string resolve
throw new Win32Exception(errorCode, "Failed to spawn process");
}

return new SafeChildProcessHandle(pidfd, pid, exitPipeFd);
return new SafeChildProcessHandle(pidfd, pid);
}
finally
{
Expand Down Expand Up @@ -171,7 +159,7 @@ private ProcessExitStatus WaitForExitCore()

private bool TryWaitForExitCore(int milliseconds, [NotNullWhen(true)] out ProcessExitStatus? exitStatus)
{
switch (try_wait_for_exit(this, ProcessId, _exitPipeFd, milliseconds, out int exitCode, out int rawSignal, out int hasTimedout))
switch (try_wait_for_exit(this, ProcessId, milliseconds, out int exitCode, out int rawSignal, out int hasTimedout))
{
case -1:
int errno = Marshal.GetLastPInvokeError();
Expand All @@ -187,7 +175,7 @@ private bool TryWaitForExitCore(int milliseconds, [NotNullWhen(true)] out Proces

private ProcessExitStatus WaitForExitOrKillOnTimeoutCore(int milliseconds)
{
switch (wait_for_exit_or_kill_on_timeout(this, ProcessId, _exitPipeFd, milliseconds, out int exitCode, out int rawSignal, out int hasTimedout))
switch (wait_for_exit_or_kill_on_timeout(this, ProcessId, milliseconds, out int exitCode, out int rawSignal, out int hasTimedout))
{
case -1:
int errno = Marshal.GetLastPInvokeError();
Expand Down Expand Up @@ -217,7 +205,7 @@ private async Task<ProcessExitStatus> WaitForExitAsyncCore(CancellationToken can

return await Task.Run(() =>
{
switch (try_wait_for_exit_cancellable(this, ProcessId, _exitPipeFd, (int)readHandle.DangerousGetHandle(), out int exitCode, out int rawSignal))
switch (try_wait_for_exit_cancellable(this, ProcessId, (int)readHandle.DangerousGetHandle(), out int exitCode, out int rawSignal))
{
case -1:
int errno = Marshal.GetLastPInvokeError();
Expand Down Expand Up @@ -250,7 +238,7 @@ private async Task<ProcessExitStatus> WaitForExitOrKillOnCancellationAsyncCore(C

return await Task.Run(() =>
{
switch (try_wait_for_exit_cancellable(this, ProcessId, _exitPipeFd, (int)readHandle.DangerousGetHandle(), out int exitCode, out int rawSignal))
switch (try_wait_for_exit_cancellable(this, ProcessId, (int)readHandle.DangerousGetHandle(), out int exitCode, out int rawSignal))
{
case -1:
int errno = Marshal.GetLastPInvokeError();
Expand Down Expand Up @@ -339,7 +327,6 @@ private static unsafe partial int spawn_process(
byte* working_dir,
out int pid,
out int pidfd,
out int exit_pipe_fd,
int kill_on_parent_death,
int create_suspended,
int create_new_process_group,
Expand All @@ -354,13 +341,13 @@ private static unsafe partial int spawn_process(
private static partial int wait_for_exit_and_reap(SafeChildProcessHandle pidfd, int pid, out int exitCode, out int signal);

[LibraryImport("pal_process", SetLastError = true)]
private static partial int try_wait_for_exit(SafeChildProcessHandle pidfd, int pid, int exitPipeFd, int timeout_ms, out int exitCode, out int signal, out int hasTimedout);
private static partial int try_wait_for_exit(SafeChildProcessHandle pidfd, int pid, int timeout_ms, out int exitCode, out int signal, out int hasTimedout);

[LibraryImport("pal_process", SetLastError = true)]
private static partial int try_wait_for_exit_cancellable(SafeChildProcessHandle pidfd, int pid, int exitPipeFd, int cancelPipeFd, out int exitCode, out int signal);
private static partial int try_wait_for_exit_cancellable(SafeChildProcessHandle pidfd, int pid, int cancelPipeFd, out int exitCode, out int signal);

[LibraryImport("pal_process", SetLastError = true)]
private static partial int wait_for_exit_or_kill_on_timeout(SafeChildProcessHandle pidfd, int pid, int exitPipeFd, int timeout_ms, out int exitCode, out int signal, out int hasTimedout);
private static partial int wait_for_exit_or_kill_on_timeout(SafeChildProcessHandle pidfd, int pid, int timeout_ms, out int exitCode, out int signal, out int hasTimedout);

[LibraryImport("pal_process", SetLastError = true)]
private static partial int try_get_exit_code(SafeChildProcessHandle pidfd, int pid, out int exitCode, out int signal);
Expand All @@ -378,8 +365,6 @@ private static SafeChildProcessHandle OpenCore(int processId)
throw new Win32Exception(errno, $"Failed to open process {processId} (errno={errno})");
}

// Create a SafeChildProcessHandle with the pidfd (or -1 if not available)
// and the process ID. No exit pipe is available, so we use public ctor.
return new SafeChildProcessHandle(pidfd, processId, ownsHandle: true);
return new SafeChildProcessHandle(pidfd, processId);
}
}
Loading