Implement SafeProcessHandle.Open API#126705
Conversation
Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/f57caa85-c528-444f-ab43-a628d6ddd488 Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>
Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/f57caa85-c528-444f-ab43-a628d6ddd488 Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>
adamsitnik
left a comment
There was a problem hiding this comment.
@copilot give my feedback a try. Run all process tests and ensure they pass before you push any changes.
|
Tagging subscribers to this area: @dotnet/area-system-diagnostics-process |
…ss with outPidfd parameter Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/664957d4-993f-4f40-aa79-ce45ec55fd11 Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>
adamsitnik
left a comment
There was a problem hiding this comment.
@copilot address my feedback
…acOS posix_spawn path Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/ed9ebae7-b0ac-4a66-a222-8f7305c55a9b Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>
… use int.MinValue for non-pidfd handles Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/99759f32-cf6d-48fa-9f60-1ec4f2630ad2 Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>
…shandle-open-api # Conflicts: # src/libraries/Common/src/Interop/Unix/System.Native/Interop.ForkAndExecProcess.cs # src/libraries/System.Diagnostics.Process/src/Microsoft/Win32/SafeHandles/SafeProcessHandle.Unix.cs # src/libraries/System.Diagnostics.Process/src/Microsoft/Win32/SafeHandles/SafeProcessHandle.Windows.cs # src/libraries/System.Diagnostics.Process/tests/SafeProcessHandleTests.cs # src/native/libs/System.Native/pal_process.c # src/native/libs/System.Native/pal_process.h # src/native/libs/System.Native/pal_process_wasi.c Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>
Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/4b27183c-4bf6-4085-9a44-15cce51c2b1f Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>
adamsitnik
left a comment
There was a problem hiding this comment.
@copilot please address my feedback
| [ConditionalFact(typeof(RemoteExecutor), nameof(RemoteExecutor.IsSupported))] | ||
| public void Open_RunningProcess_ReturnsValidHandle() | ||
| { | ||
| Process process = CreateProcess(static () => |
There was a problem hiding this comment.
| Process process = CreateProcess(static () => | |
| using Process process = CreateProcess(static () => |
| [ConditionalFact(typeof(RemoteExecutor), nameof(RemoteExecutor.IsSupported))] | ||
| public void Open_ThenKill_TerminatesProcess() | ||
| { | ||
| Process process = CreateProcess(static () => |
There was a problem hiding this comment.
| Process process = CreateProcess(static () => | |
| using Process process = CreateProcess(static () => |
| using SafeProcessHandle handle = SafeProcessHandle.Open(process.Id); | ||
| handle.Kill(); | ||
|
|
||
| Assert.True(process.WaitForExit(WaitInMS)); |
There was a problem hiding this comment.
We need to use handle here as well
| Assert.True(process.WaitForExit(WaitInMS)); | |
| Assert.True(handle.WaitForExit(WaitInMS)); |
There was a problem hiding this comment.
Fixed in 9fd4c33. Used handle.TryWaitForExit(TimeSpan.FromMilliseconds(WaitInMS), out _) since SafeProcessHandle doesn't have a WaitForExit(int) overload.
| #if defined(__linux__) | ||
| int pidfd = (int)syscall(SYS_pidfd_open, pid, 0); |
There was a problem hiding this comment.
@copilot is SYS_pidfd_open available on Android as well? If so, we should do it for both platforms
There was a problem hiding this comment.
Yes, SYS_pidfd_open is available on Android. The __linux__ macro is defined on Android, so both the syscall number definitions (lines 43-56) and the TryOpenPidfd function body (line 352) already cover Android — no change needed.
| throw new Win32Exception(); | ||
| } | ||
|
|
||
| return new SafeProcessHandle(pidfd != -1 ? pidfd : int.MinValue, processId); |
There was a problem hiding this comment.
The SafeProcessHandle that is created here can't be used for waiting for the process to exit. We need to obtain the wait state holder for given process
There was a problem hiding this comment.
Fixed in 9fd4c33. OpenCore now creates a ProcessWaitState.Holder for the process, which enables wait operations on the returned handle.
| Validate(); | ||
|
|
||
| if (_waitStateHolder is null) | ||
| if (_waitStateHolder is not null) |
There was a problem hiding this comment.
_waitStateHolder must always be present
There was a problem hiding this comment.
Fixed in 9fd4c33. Removed the _processId field and the private (int pidfd, int processId) constructor. OpenCore now uses new ProcessWaitState.Holder(processId) + the standard constructor, so _waitStateHolder is always present.
Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/72aa4a5d-d91c-4ef1-86ff-75322b4676bc Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>
All feedback addressed in 9fd4c33. Key changes:
All 617 process tests pass (0 failures, 5 skipped). |
Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/3954e392-7975-49be-969f-eceeacf7b568 Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>
Description
Implements the
SafeProcessHandle.Open(int processId)API that opens a handle to an existing process by its ID.Changes
Native layer (
pal_process.c,pal_process.h,pal_process_wasi.c):TryOpenPidfdlinux-specific helper that usespidfd_opensyscall (works on both Linux and Android since both define__linux__)SystemNative_ForkAndExecProcesswithint32_t* outPidfdoutput parameterSystemNative_OpenProcessthat validates the process exists viakill(pid, 0)and attempts to obtain a pidfdManaged layer:
Interop.ForkAndExecProcess.cs: Addedout int lpPidfdparameter to both the managed wrapper and P/Invoke declarationSafeProcessHandle.Unix.cs:OpenCorecreates aProcessWaitState.Holderfor the target process (ensuring wait/kill operations work on the returned handle) and stores the pidfd when availableSafeProcessHandle.Windows.cs:OpenCoreusesOpenProcesswithPROCESS_QUERY_LIMITED_INFORMATION | SYNCHRONIZE | PROCESS_TERMINATESafeProcessHandle.cs: PublicOpen(int processId)method with argument validationTests (
SafeProcessHandleTests.cs):Open_InvalidProcessId_ThrowsArgumentOutOfRangeException— validates argument checkingOpen_NonExistentProcessId_ThrowsWin32Exception— validates error for dead PIDsOpen_RunningProcess_ReturnsValidHandle— validates handle propertiesOpen_ThenKill_TerminatesProcess— validates kill + wait via the opened handleDesign decisions
_waitStateHolderis always present inSafeProcessHandle, enabling wait/kill operations on handles obtained viaOpenint.MinValueis used as the handle value to avoidIsInvalidreturning true_pidfdfield and closed inReleaseHandleTesting
All 617 process tests pass (0 failures, 5 skipped).