Uh oh!
There was an error while loading. Please reload this page.
Add new process management APIs to SafeProcessHandle - #124375
Add new process management APIs to SafeProcessHandle#124375adamsitnik with Copilot wants to merge 59 commits into
Conversation
Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>
Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>
Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>
Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>
Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>
Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>
Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>
…, Theory for utils Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>
…h for sh Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>
…syntax Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>
Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>
… remove dead code Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>
Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>
Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>
Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>
…names Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>
Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>
…s, and Windows implementation Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>
Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
| } | ||
| } | ||
| internal static int GetTimeoutInMilliseconds(TimeSpan timeout) |
There was a problem hiding this comment.
| internalstaticintGetTimeoutInMilliseconds(TimeSpantimeout) | |
| internalstaticintToTimeoutInMilliseconds(TimeSpantimeout) |
This method is called ToTimeoutMilliseconds in other places.
We have identical multiple copies of this method. It is candidate for a helper API.
There was a problem hiding this comment.
Do we actually need to convert the TimeSpan to int here? There are WaitHandle overloads that take TimeSpan. Can we just call those instead?
There was a problem hiding this comment.
Do we actually need to convert the TimeSpan to int here? There are WaitHandle overloads that take TimeSpan.
You are right, on Windows I could just pass TimeSpan to the Core implementation, but on Unix I need raw int milliseconds to pass it to poll and similar sys-calls.
| private void SendSignalCore(PosixSignal signal) | ||
| { | ||
| if (signal == PosixSignal.SIGKILL) |
There was a problem hiding this comment.
Nit: Would be simpler to just throw PlatformNotSupportedException from this method unconditionally on Windows, and mark this method as unsupported on Windows? I expect that killing the process is typically going to be done by the Kill API. Handling PosixSignal.SIGKILL here does not have a lot of value.
There was a problem hiding this comment.
Handling
PosixSignal.SIGKILLhere does not have a lot of value.
I agree it's not a lot, but I can imagine that some users with Unix background would prefer using Signal(PosixSignal.SIGKILL) over Kill.
It's not something that I have very strong opinion about.
jkotas
commented
Mar 17, 2026
LGTM modulo feedback |
- don't swallow kill exceptions by WaitForExitOrKill* methods - rename helper method
Uh oh!
There was an error while loading. Please reload this page.
Co-authored-by: Adam Sitnik <adam.sitnik@gmail.com>
Description
Implements the approved API surface for
SafeProcessHandle(#123380): process lifecycle management viaStart,Open,Kill,Signal,SignalProcessGroup, andWaitForExitoverloads. Windows implementation complete; Unix stubs throwNotImplementedException(separate PR).Public API
Open(int processId)— opens existing process handleStart(ProcessStartOptions, SafeFileHandle?, SafeFileHandle?, SafeFileHandle?)— create process with explicit stdio handlesKill()— terminate processSignal(PosixSignal)/SignalProcessGroup(PosixSignal)— send signal; accepts raw signal numbers likePosixSignalRegistration.CreateWaitForExit(),TryWaitForExit(TimeSpan, out ProcessExitStatus?),WaitForExitOrKillOnTimeout(TimeSpan)— synchronous waitWaitForExitAsync(CancellationToken),WaitForExitOrKillOnCancellationAsync(CancellationToken)— async waitInternal for now (pending follow-up):
ProcessId,StartSuspended,Resume,KillProcessGroup.Windows implementation
STARTUPINFOEX+PROC_THREAD_ATTRIBUTE_HANDLE_LISTfor explicit handle inheritanceKillOnParentExitand process group termination (best-effort emulation of Unix process groups)DangerousAddRef/DangerousReleaseonInheritedHandlesinPrepareHandleAllowListand onthisinKillCoreto prevent use-after-free races with concurrentDisposeInterlocked.Exchangefor_threadHandleand_processGroupJobHandleinReleaseHandle;Volatile.Readfor_processGroupJobHandleaccess elsewhereWaitForSingleObject(SafeProcessHandle, ...)directly — no handle duplication viaProcessWaitHandleProcessWaitHandleforRegisterWaitForSingleObjectNativeMemory.Allocwith two-arg overflow-safe version; typed pointers (IntPtr*,void*)finally; error check immediately afterCreateProcessArchitecture —
ProcessUtilsas shared dependencyProcessUtils.csholdss_processStartLock(ReaderWriterLockSlim) — avoidsProcess↔SafeProcessHandledependency cycleProcessUtils.Windows.csholdsBuildArgs(string, IList<string>?)andGetEnvironmentVariablesBlockProcess.Windows.csacquires write lock;SafeProcessHandle.Windows.csacquires read lockInterop additions
Interop.JobObjects.cs,Interop.ProcThreadAttributeList.cs,Interop.ConsoleCtrl.cs(consolidated),Interop.HandleInformation.cs(extended),Interop.ResumeThread_IntPtr.cs,Interop.WaitForSingleObject_SafeProcessHandle.csTests
SafeProcessHandleTests.cs— start/kill/wait/timeout/signal tests with Nano Server support (pingfallback); signal tests as[Theory]with[InlineData]💬 We'd love your input! Share your thoughts on Copilot coding agent in our 2 minute survey.