Implement SafeProcessHandle APIs for macOS#124923
Implement SafeProcessHandle APIs for macOS#124923Copilot wants to merge 11 commits intocopilot/add-new-apis-to-safeprocesshandlefrom
Conversation
|
Tagging subscribers to this area: @dotnet/area-system-diagnostics-process |
Co-authored-by: adamsitnik <[email protected]>
Co-authored-by: adamsitnik <[email protected]>
…rocess path) Co-authored-by: adamsitnik <[email protected]>
adamsitnik
left a comment
There was a problem hiding this comment.
@copilot please address my feedback.
Moreover, please modify the .yml file that is required to let the CI run for this branch. I am not an expert in this area, but I think it should be enough to modify this file:
runtime/eng/pipelines/runtime.yml
Lines 33 to 37 in fdaebbf
and list copilot/*.* after release/*.*
- release/*.*
- copilot/*.*
src/libraries/Common/src/Interop/Unix/System.Native/Interop.SpawnProcess.cs
Outdated
Show resolved
Hide resolved
...braries/System.Diagnostics.Process/src/Microsoft/Win32/SafeHandles/SafeProcessHandle.Unix.cs
Outdated
Show resolved
Hide resolved
src/libraries/System.Diagnostics.Process/src/System/Diagnostics/Process.Unix.cs
Outdated
Show resolved
Hide resolved
src/libraries/System.Diagnostics.Process/tests/SafeProcessHandleTests.cs
Outdated
Show resolved
Hide resolved
src/libraries/System.Diagnostics.Process/tests/SafeProcessHandleTests.cs
Outdated
Show resolved
Hide resolved
src/libraries/System.Diagnostics.Process/tests/SafeProcessHandleTests.cs
Show resolved
Hide resolved
src/libraries/System.Diagnostics.Process/tests/SafeProcessHandleTests.cs
Outdated
Show resolved
Hide resolved
src/libraries/System.Diagnostics.Process/tests/SafeProcessHandleTests.cs
Outdated
Show resolved
Hide resolved
src/libraries/System.Diagnostics.Process/tests/SafeProcessHandleTests.Unix.cs
Outdated
Show resolved
Hide resolved
src/libraries/System.Diagnostics.Process/tests/SafeProcessHandleTests.Unix.cs
Show resolved
Hide resolved
…on throws, update tests, add CI branch trigger Co-authored-by: adamsitnik <[email protected]>
All feedback addressed and |
There was a problem hiding this comment.
Pull request overview
This PR implements SafeProcessHandle APIs for macOS using posix_spawn for process creation and kqueue for wait/timeout/cancellation operations. The implementation provides parity with the Windows implementation, enabling cross-platform process management through the new SafeProcessHandle APIs.
Changes:
- Native layer: Added macOS-specific implementations using
posix_spawn,kqueue, andwaitpidfor process creation and management - Managed layer: Implemented all core SafeProcessHandle methods (
Start,Open,WaitForExit*,Kill,Resume,Signal) with proper error handling - Code refactoring: Extracted shared utility methods (
CreateEnvp,AllocNullTerminatedArray,FreeArray) fromInterop.ForkAndExecProcess.cstoProcessUtils.Unix.csfor reuse - Tests: Extended cross-platform tests to support macOS and added macOS-specific signal tests
Reviewed changes
Copilot reviewed 16 out of 16 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| src/native/libs/configure.cmake | Added CMake feature detection for posix_spawn APIs and kqueue on macOS |
| src/native/libs/Common/pal_config.h.in | Added configuration defines for detected posix_spawn features |
| src/native/libs/System.Native/pal_process.h | Declared new native API functions for process spawning, signaling, and waiting |
| src/native/libs/System.Native/pal_process.c | Implemented macOS-specific process APIs using posix_spawn and kqueue, including signal mapping |
| src/native/libs/System.Native/pal_process_wasi.c | Added ENOTSUP stubs for WASI platform |
| src/native/libs/System.Native/entrypoints.c | Registered new native function entry points |
| src/libraries/Common/src/Interop/Unix/System.Native/Interop.SpawnProcess.cs | Added P/Invoke declarations for new native APIs |
| src/libraries/Common/src/Interop/Unix/System.Native/Interop.ForkAndExecProcess.cs | Refactored to use shared ProcessUtils methods |
| src/libraries/System.Diagnostics.Process/src/System/Diagnostics/ProcessUtils.Unix.cs | Added shared utility methods for environment and array marshalling |
| src/libraries/System.Diagnostics.Process/src/System/Diagnostics/Process.Unix.cs | Updated to use ProcessUtils.CreateEnvp instead of local implementation |
| src/libraries/System.Diagnostics.Process/src/Microsoft/Win32/SafeHandles/SafeProcessHandle.Unix.cs | Implemented all SafeProcessHandle core methods for macOS |
| src/libraries/System.Diagnostics.Process/src/System.Diagnostics.Process.csproj | Added Interop.SpawnProcess.cs and Interop.Pipe.cs to Unix builds |
| src/libraries/System.Diagnostics.Process/tests/SafeProcessHandleTests.cs | Extended platform support to include macOS and updated tests for cross-platform compatibility |
| src/libraries/System.Diagnostics.Process/tests/SafeProcessHandleTests.Unix.cs | Added macOS-specific signal tests |
| src/libraries/System.Diagnostics.Process/tests/System.Diagnostics.Process.Tests.csproj | Added SafeProcessHandleTests.Unix.cs to Unix test builds |
| eng/pipelines/runtime.yml | Added copilot/. branch trigger (intended for development, should be removed) |
src/libraries/System.Diagnostics.Process/tests/SafeProcessHandleTests.cs
Outdated
Show resolved
Hide resolved
adamsitnik
left a comment
There was a problem hiding this comment.
@copilot please address all unresolved feedback
…ping, fix pwd test Co-authored-by: adamsitnik <[email protected]>
All unresolved feedback addressed in cdd13b0: simplified |
adamsitnik
left a comment
There was a problem hiding this comment.
@copilot please give my suggestion a try.
…hecks Co-authored-by: adamsitnik <[email protected]>
Co-authored-by: adamsitnik <[email protected]>
adamsitnik
left a comment
There was a problem hiding this comment.
@copilot please address my feedback
Also, annotate the Open_CurrentProcess_Succeeds test with [PlatformSpecific(TestPlatforms.Windows)]
…der args, add GetEnvVars helper, restore HAVE_POSIX_SPAWN_FILE_ACTIONS_ADDCHDIR_NP, fix test Co-authored-by: adamsitnik <[email protected]>
Annotated |
adamsitnik
left a comment
There was a problem hiding this comment.
@copilot please apply my suggestion
Co-authored-by: adamsitnik <[email protected]>
|
@copilot please invoke the code-review skill and post the analysis/results as a comment on this PR |
🤖 Copilot Code Review — PR #115913Holistic AssessmentMotivation: This PR implements the macOS-specific managed and native layers for the new Approach: The approach is solid — using Summary: Detailed Findings
|
Co-authored-by: adamsitnik <[email protected]>
| ) | ||
| { | ||
| #if defined(__APPLE__) && !defined(TARGET_MACCATALYST) && !defined(TARGET_TVOS) | ||
| // ========== POSIX_SPAWN PATH (macOS) ========== |
There was a problem hiding this comment.
@wfurt If you could take some time to review this PR, I would appreciate it a lot.
To tell the long story, I want to introduce a low-level API that will allow to build anything process-related on top of it.
Since it's a new API, I don't need to worry about breaking changes and I really want us to stop inheriting all file descriptors when starting a process. On macOS, this can be done with POSIX_SPAWN_CLOEXEC_DEFAULT which is supported by posix_spawn which based on my benchmarking works way FASTER on macOS compared to typical fork/execv.
For other process-related methods I use kqueue to monitor for process exit (with a timeout).
Some of the native methods accept pidfd it's short for process descriptors, which will be used and introduced in separate PR for Linux (#124979, it's still WIP and not ready for review)
Description
Implements the macOS-specific managed and native layers for the new
SafeProcessHandleAPIs (Start,Open,WaitForExit*,Kill,Resume,Signal), usingposix_spawnfor process creation andkqueuefor wait/timeout/cancellation.Managed changes
SafeProcessHandle.Unix.cs: Full implementation ofStartCore,OpenCore,WaitForExitCore,TryWaitForExitCore,WaitForExitOrKillOnTimeoutCore,WaitForExitAsyncCore,WaitForExitOrKillOnCancellationAsyncCore,KillCore,ResumeCore,SendSignalCore. UsesNoPidFd = int.MinValue(not-1) since the handle derives fromSafeHandleZeroOrMinusOneIsInvalid. All error paths usethrow new Win32Exception()(parameterless) to let it fetch the last error automatically.ProcessUtils.Unix.cs: ExtractedCreateEnvp,AllocNullTerminatedArray,FreeArrayasinternalshared methods, reused by bothProcess.Unix.csandSafeProcessHandle.Unix.cs.Process.Unix.cs: Inlined the privateCreateEnvpwrapper to callProcessUtils.CreateEnvpdirectly.Interop.SpawnProcess.cs: NewLibraryImportdeclarations (EntryPoint = "SystemNative_*") forSpawnProcess,SendSignal,WaitForExitAndReap,TryWaitForExit,TryWaitForExitCancellable,WaitForExitOrKillOnTimeout,TryGetExitCode,OpenProcess. Thedetachedparameter is omitted as the API proposal is still pending review.Interop.ForkAndExecProcess.cs: Delegates to sharedProcessUtilsmethods.Interop.Pipe.csandInterop.SpawnProcess.csfor Unix builds.Native changes
pal_process.c: macOS implementation usingposix_spawnwithPOSIX_SPAWN_CLOEXEC_DEFAULT,posix_spawn_file_actions_addinherit_np,posix_spawn_file_actions_addchdir_np,POSIX_SPAWN_START_SUSPENDED. The implementation is guarded by#if defined(__APPLE__) && !defined(TARGET_MACCATALYST) && !defined(TARGET_TVOS)to exclude Mac Catalyst and tvOS (iOS is supported).posix_spawn_file_actions_addchdir_npretainsHAVE_POSIX_SPAWN_FILE_ACTIONS_ADDCHDIR_NPfeature detection since it is not available on tvOS. Wait functions usekqueue/EVFILT_PROC/NOTE_EXIT(guarded by existingHAVE_KQUEUE) for timeout and cancellation support. Signal mapping reusesSystemNative_GetPlatformSignalNumberandTryConvertSignalCodeToPosixSignalfrompal_signal.cinstead of duplicating the logic. Environment variable resolution is extracted into aGetEnvVarshelper for reuse.OpenProcessuseskill(pid, 0)to check process existence without requiring a child-process relationship.pal_signal.c/pal_signal.h: MadeTryConvertSignalCodeToPosixSignalnon-static and added its declaration to the header for reuse bypal_process.c.pal_process_wasi.c: Stubs returning-1witherrno = ENOTSUP.pal_process.h: New function declarations with reorderedSpawnProcessarguments (path, argv, envp, working_dir, inherited_handles, inherited_handles_count, stdin/stdout/stderr fds, flags, out params).entrypoints.c: NewDllImportEntryentries.configure.cmake/pal_config.h.in: AddedHAVE_POSIX_SPAWN_FILE_ACTIONS_ADDCHDIR_NPfeature detection (not available on tvOS). No otherHAVE_POSIX_SPAWN*defines are added — macOS platform checks (#ifdef __APPLE__) are used instead. ExistingHAVE_KQUEUEis reused forsys/event.hinclusion.Test changes
SafeProcessHandleTests.cs: Extended[PlatformSpecific]toTestPlatforms.OSX | TestPlatforms.Windows. AllProcessStartOptionscreation uses platform detection (OperatingSystem.IsWindows()ternary).CreateTenSecondSleepreturnssleep 10on Unix.Start_WithNoArguments_Succeedsuseshostnameon Windows andpwdon Unix (platform-specific, sincepwdis not a standalone executable on Windows). Kill tests assertPosixSignal.SIGKILLand exit code > 128 on Unix.Open_CurrentProcess_Succeedsis annotated[PlatformSpecific(TestPlatforms.Windows)].SafeProcessHandleTests.Unix.cs: macOS-specific tests forSignal(SIGTERM),Signal(SIGINT), invalid signal, and signal-to-exited-process behavior. All long-running tests useCreateTenSecondSleep().CI changes
eng/pipelines/runtime.yml: Addedcopilot/*.*to CI branch triggers to enable pipeline runs for this branch.💬 We'd love your input! Share your thoughts on Copilot coding agent in our 2 minute survey.