Uh oh!
There was an error while loading. Please reload this page.
Implement ProcessStartInfo.KillOnParentExit for Windows - #126699
Conversation
Add KillOnParentExit property to ProcessStartInfo that terminates child processes when the parent process exits. Windows implementation uses Job Objects with JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE flag. For CreateProcess: uses PROC_THREAD_ATTRIBUTE_JOB_LIST for atomic assignment. For CreateProcessWithLogonW: starts suspended, assigns to job, then resumes. Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/61612ca1-930c-4836-8554-d143d05c8321 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
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.
Uh oh!
There was an error while loading. Please reload this page.
…py path, add user credentials test, fix pid reporting via stdout, remove nop UseShellExecute test Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/c4dd95b4-cd8e-4740-83f9-7358444c04ce Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>
- simplify the tests - avoid duplication!!
There was a problem hiding this comment.
Pull request overview
Implements Windows support for ProcessStartInfo.KillOnParentExit by using Windows Job Objects to ensure spawned processes are terminated when the parent exits.
Changes:
- Added
ProcessStartInfo.KillOnParentExitAPI surface (implementation + ref assembly) and validation againstUseShellExecute. - Implemented Windows job-object based process start paths (CreateProcess job-list attribute, and CreateProcessWithLogonW suspended + assign + resume).
- Added Windows-focused tests validating the behavior.
Reviewed changes
Copilot reviewed 10 out of 10 changed files in this pull request and generated 6 comments.
Show a summary per file
| File | Description |
|---|---|
| src/libraries/System.Diagnostics.Process/tests/System.Diagnostics.Process.Tests.csproj | Includes the new KillOnParentExit test file in the test project. |
| src/libraries/System.Diagnostics.Process/tests/ProcessStartInfoTests.cs | Extends existing Windows credential tests to cover KillOnParentExit on that path. |
| src/libraries/System.Diagnostics.Process/tests/KillOnParentExitTests.cs | Adds new Windows tests validating KillOnParentExit behavior under various parent-exit scenarios. |
| src/libraries/System.Diagnostics.Process/src/System/Diagnostics/ProcessStartInfo.cs | Adds the KillOnParentExit property, docs, and validation with UseShellExecute. |
| src/libraries/System.Diagnostics.Process/src/System.Diagnostics.Process.csproj | Links in the new Windows job-object interop file. |
| src/libraries/System.Diagnostics.Process/src/Resources/Strings.resx | Adds a resource string for the KillOnParentExit + UseShellExecute validation. |
| src/libraries/System.Diagnostics.Process/src/Microsoft/Win32/SafeHandles/SafeProcessHandle.Windows.cs | Windows implementation: shared job handle, job-list attribute support, and logon path job assignment. |
| src/libraries/System.Diagnostics.Process/ref/System.Diagnostics.Process.cs | Adds the KillOnParentExit property to the reference assembly surface. |
| src/libraries/Common/src/Interop/Windows/Kernel32/Interop.JobObjects.cs | Adds required job-object P/Invokes/structs/constants. |
| src/libraries/Common/src/Interop/Windows/Advapi32/Interop.ProcessOptions.cs | Adds CREATE_SUSPENDED for the CreateProcessWithLogonW suspended-start path. |
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.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
This comment has been minimized.
This comment has been minimized.
adamsitnik
left a comment
There was a problem hiding this comment.
@copilot address my feedback
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.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
…sumeThread return, remove unused using, improve VerifyProcessIsRunning polling Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/06c58cfa-bdef-4f35-9345-9ab03e7dc542 Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>
Uh oh!
There was an error while loading. Please reload this page.
jkotas
commented
Apr 11, 2026
@copilot Address this feedback by replacing the local ResumeThread with the shared copy |
…d Interop.Kernel32.ResumeThread Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/e8bb36bc-5c71-4723-a32c-17e87d762370 Co-authored-by: jkotas <6668460+jkotas@users.noreply.github.com>
Replaced the local |
…al ResumeThread P/Invoke Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/e8bb36bc-5c71-4723-a32c-17e87d762370 Co-authored-by: jkotas <6668460+jkotas@users.noreply.github.com>
Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/f3703368-dbc7-4226-8258-1bb793d93faf 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.
adamsitnik
commented
Apr 11, 2026
…, unnecessary assert, reduce ConfigureExtendedStartupInfo args Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/2dd25b7c-da4a-4ed0-a9b3-cc6561f14aeb Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>
Description
Implements the
ProcessStartInfo.KillOnParentExitproperty for Windows, which terminates child processes when the parent process exits. This is the Windows part of theKillOnParentExitfeature.API approved at #125838 (comment)
Changes Made
New API surface:
KillOnParentExitproperty toProcessStartInfowith[SupportedOSPlatform("windows")]attribute (linux support will be added in upcoming PRs)ref/System.Diagnostics.Process.cs) with matching[SupportedOSPlatformAttribute("windows")]JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSEWindows implementation (
SafeProcessHandle.Windows.cs):SafeJobHandlewithJOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSEflag, shared across all child processes withKillOnParentExit=trueCreateProcesspath (no user credentials): usesPROC_THREAD_ATTRIBUTE_JOB_LISTin the extended startup info for atomic job assignment at process creationCreateProcessWithLogonWpath (with user credentials): starts the process suspended, assigns it to the job object viaAssignProcessToJobObject, then resumes the thread only on the happy path — on failure, the suspended process is terminatedResumeThreadreturn value is checked; failure throwsWin32Exceptionand the suspended process is terminatedAssignJobAndResumeThreadtakes(IntPtr hThread, SafeProcessHandle procSH)and usesprocSHconsistently for all process handle operations (no mixing ofprocessInfo.hProcessandprocSH)ConfigureExtendedStartupInforeturnsbooland the caller setscreationFlags,startupInfoEx.StartupInfo.cb, andstartupInfoEx.lpAttributeListto reduce the number of method argumentsstring.IsNullOrEmpty(startInfo.UserName)for defensive checks when determining the code pathP/Invoke definitions:
Interop.JobObjects.cs:CreateJobObjectW,SetInformationJobObject,AssignProcessToJobObject(acceptsSafeProcessHandle),JOBOBJECT_EXTENDED_LIMIT_INFORMATION,IO_COUNTERS,JOBOBJECTINFOCLASSstructs/enums,SafeJobHandle,PROC_THREAD_ATTRIBUTE_JOB_LISTconstantInterop.ResumeThread.cs:ResumeThreadP/Invoke returninguint(matching nativeDWORD) in its own dedicated file (following the pattern ofInterop.TerminateProcess.cs,Interop.GetExitCodeProcess.cs, etc.)IO_COUNTERSandJOBOBJECT_EXTENDED_LIMIT_INFORMATIONusenuintfor fields representing numerical values (sizes, limits, affinity masks) per interop conventionResumeThreadP/Invoke inProcessHandlesTests.Windows.cswith the sharedInterop.Kernel32.ResumeThread, eliminating the duplicate declaration and aligning the test code with the productionuint/0xFFFFFFFFpatternValidation:
ProcessStartInfo.ThrowIfInvalidto throwInvalidOperationExceptionwhenKillOnParentExitis combined withUseShellExecuteKillOnParentExitCannotBeUsedWithUseShellExecutestring resourceTests (
KillOnParentExitTests.cs):KillOnParentExit_DefaultsToFalse/KillOnParentExit_CanBeSetToTrue— property basicsKillOnParentExit_WithUseShellExecute_Throws— validation testKillOnParentExit_ProcessStartsAndExitsNormally— smoke testKillOnParentExit_KillsTheChild_WhenParentExits— verifies child is killed (enabled=true) or survives (enabled=false) on normal parent exit, reports grandchild pid via stdoutKillOnParentExit_KillsTheChild_WhenParentIsKilled— same when parent is forcefully killedKillOnParentExit_KillsTheChild_WhenParentCrashes— same when parent crashes (access violation)ProcessStartInfoTests.TestUserCredentialsPropertiesOnWindows(admin/OuterLoop)