Conversation
…eHelper to private static methods Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/6cd5d18a-42f4-41d2-9ed4-a230ebb3c71a Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>
adamsitnik
left a comment
There was a problem hiding this comment.
@copilot please also address #126192 (comment) and #126192 (comment)
Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/e7d88dfb-ddec-4d6c-b371-7097a11d6d45 Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>
Done in 7b2fad9:
|
...ries/System.Diagnostics.Process/src/Microsoft/Win32/SafeHandles/SafeProcessHandle.Windows.cs
Outdated
Show resolved
Hide resolved
Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/faf61926-cc6a-42c0-a8c6-f0fec98e0b93 Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>
...ries/System.Diagnostics.Process/src/Microsoft/Win32/SafeHandles/SafeProcessHandle.Windows.cs
Outdated
Show resolved
Hide resolved
...ries/System.Diagnostics.Process/src/Microsoft/Win32/SafeHandles/SafeProcessHandle.Windows.cs
Outdated
Show resolved
Hide resolved
Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/9134d130-f2dc-4ad8-800b-2dbb7a35a509 Co-authored-by: jkotas <6668460+jkotas@users.noreply.github.com>
...ries/System.Diagnostics.Process/src/Microsoft/Win32/SafeHandles/SafeProcessHandle.Windows.cs
Show resolved
Hide resolved
Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/bd35b541-ebf3-4f48-af2a-9e7b588d5567 Co-authored-by: jkotas <6668460+jkotas@users.noreply.github.com>
...ries/System.Diagnostics.Process/src/Microsoft/Win32/SafeHandles/SafeProcessHandle.Windows.cs
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
Pull request overview
Follow-up changes in System.Diagnostics.Process to incorporate post-merge feedback from #126192: documentation fix, ShellExecute refactor, use of the C# field keyword, additional tests, and trimming-oriented factoring for UseShellExecute.
Changes:
- Refactors ShellExecute support by removing
ShellExecuteHelper.csand inlining ShellExecute logic intoSafeProcessHandle.Windows.cs. - Consolidates
ProcessStartInfo.UseShellExecuteinto the shared file and adds a trimming hook (EnsureShellExecuteFunc) to avoid rooting ShellExecute paths unless the property is used. - Updates
SafeProcessHandle.ProcessIdto use thefieldkeyword and adds a regression test for invalid-handle validation.
Reviewed changes
Copilot reviewed 10 out of 10 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| src/libraries/System.Diagnostics.Process/tests/SafeProcessHandleTests.cs | Adds test ensuring ProcessId throws on invalid handle. |
| src/libraries/System.Diagnostics.Process/src/System/Diagnostics/ShellExecuteHelper.cs | Deletes helper class; logic is moved into SafeProcessHandle.Windows.cs. |
| src/libraries/System.Diagnostics.Process/src/System/Diagnostics/ProcessStartInfo.cs | Moves UseShellExecute to shared file and invokes trimming hook in setter. |
| src/libraries/System.Diagnostics.Process/src/System/Diagnostics/ProcessStartInfo.Win32.cs | Removes Win32-specific UseShellExecute property. |
| src/libraries/System.Diagnostics.Process/src/System/Diagnostics/ProcessStartInfo.Unix.cs | Removes Unix-specific UseShellExecute property. |
| src/libraries/System.Diagnostics.Process/src/System/Diagnostics/Process.Windows.cs | Removes redundant UseShellExecute = false assignments. |
| src/libraries/System.Diagnostics.Process/src/System.Diagnostics.Process.csproj | Removes ShellExecuteHelper.cs from compilation items. |
| src/libraries/System.Diagnostics.Process/src/Microsoft/Win32/SafeHandles/SafeProcessHandle.cs | Adds EnsureShellExecuteFunc; converts ProcessId to field keyword backing. |
| src/libraries/System.Diagnostics.Process/src/Microsoft/Win32/SafeHandles/SafeProcessHandle.Windows.cs | Inlines ShellExecute/STA-thread logic and routes ShellExecute through delegate for trimming. |
| src/libraries/System.Diagnostics.Process/src/Microsoft/Win32/SafeHandles/SafeProcessHandle.Unix.cs | Adjusts shell-execute routing via delegate, adds doc comment fix, and factors Unix shell-execute into a method. |
...braries/System.Diagnostics.Process/src/Microsoft/Win32/SafeHandles/SafeProcessHandle.Unix.cs
Show resolved
Hide resolved
...braries/System.Diagnostics.Process/src/Microsoft/Win32/SafeHandles/SafeProcessHandle.Unix.cs
Outdated
Show resolved
Hide resolved
...braries/System.Diagnostics.Process/src/Microsoft/Win32/SafeHandles/SafeProcessHandle.Unix.cs
Outdated
Show resolved
Hide resolved
|
Hmm,, looks like one cannot depend on copilot moving code around without introducing bugs. |
src/libraries/System.Diagnostics.Process/src/System/Diagnostics/ProcessStartInfo.cs
Show resolved
Hide resolved
…eShellExecute delegate initialization Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/842a9987-1668-4933-baf7-2c38be354e11 Co-authored-by: jkotas <6668460+jkotas@users.noreply.github.com>
src/libraries/System.Diagnostics.Process/tests/SafeProcessHandleTests.cs
Outdated
Show resolved
Hide resolved
| setCredentials, userId, groupId, groups, | ||
| stdinHandle, stdoutHandle, stderrHandle, usesTerminal, | ||
| out waitStateHolder); | ||
| out ProcessWaitState.Holder? firstHolder, |
There was a problem hiding this comment.
@copilot it is fine to reuse waitStateHolder here. You do not need an extra local
There was a problem hiding this comment.
Done in 989c73f. Removed firstHolder and now output directly into waitStateHolder from ForkAndExecProcess. The ENOEXEC dispose path calls waitStateHolder?.Dispose() directly before falling through to the fallback.
…tHolder Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/bfd2bdde-ccb1-4a59-8768-45b4d935e7c4 Co-authored-by: jkotas <6668460+jkotas@users.noreply.github.com>
...braries/System.Diagnostics.Process/src/Microsoft/Win32/SafeHandles/SafeProcessHandle.Unix.cs
Outdated
Show resolved
Hide resolved
...ries/System.Diagnostics.Process/src/Microsoft/Win32/SafeHandles/SafeProcessHandle.Windows.cs
Outdated
Show resolved
Hide resolved
…afeHandles/SafeProcessHandle.Windows.cs
…afeHandles/SafeProcessHandle.Unix.cs
src/libraries/System.Diagnostics.Process/src/System/Diagnostics/ProcessStartInfo.Win32.cs
Outdated
Show resolved
Hide resolved
🤖 Copilot Code Review — PR #126314Note This review was generated by Copilot using multi-model analysis (Claude Opus 4.6, Claude Sonnet 4.5, GPT-5.4). Holistic AssessmentMotivation: The PR is a well-scoped follow-up to #126192, addressing post-merge review feedback from Approach: The delegate-dispatch pattern for trimming follows the established Summary: ✅ LGTM. The code is correct, well-reviewed by maintainers, and addresses all feedback. Two minor observations below — neither is blocking. Detailed Findings✅ Thread Safety —
|
Follow-up to #126192 addressing post-merge review comments.
Description
Fix "OS handle" doc comment (r3007938546)
SafeProcessHandle.Unix.cs:keeps the OS handle alive→keeps the handle alive—SafeWaitHandleon Unix is not an OS handle.Convert
ShellExecuteHelperto private static methods (r3005105880)ShellExecuteHelper.cs(top-level file added in Introduce SafeProcessHandle.Start and ProcessId #126192) and removed it from the.csproj.ShellExecuteOnSTAThreadandGetShellErrorintoSafeProcessHandle.Windows.csasprivate staticmethods — keeping the implementation co-located with its sole caller.GetShellErrormodernized to a switch expression, then converted to astaticlocal function insideStartWithShellExecute(adjacent to its only call site).StartWithShellExecuteEx→StartWithShellExecute.ShellExecuteOnSTAThreadfolded intoStartWithShellExecute— the split into two methods was not useful. TheShellExecuteFunctionlocal function, STA thread setup, andJoinnow live directly inStartWithShellExecute;hProcess/hInstAppare read from the struct after the thread joins rather than viaoutparameters.SHELLEXECUTEINFOaccepted by value (not by pointer); address of the local copy captured vianuint. Thecatch (EntryPointNotFoundException)block setslastError = Interop.Errors.ERROR_CALL_NOT_IMPLEMENTEDdirectly, eliminating thenotPresentbool.StartWithCreateProcessfolded intoStartCore— mirrors the Linux factoring whereStartCoredirectly contains the process creation logic rather than delegating to a separate method.Use
fieldkeyword forProcessId(r3009357619)_processIdbacking field inSafeProcessHandle.csby using the C#fieldkeyword with a property initializer:Add test for
ProcessIdvalidation (r3009467105)ProcessId_InvalidHandle_ThrowsInvalidOperationExceptiontoSafeProcessHandleTests.cs, verifying that accessingProcessIdon an invalid handle throwsInvalidOperationException.Add static delegate for
UseShellExecutetrimming supportAllows
StartWithShellExecute(and its platform-specific dependencies) to be trimmed from apps that never setUseShellExecute. Modelled on theEnsureDecompressionHandlerFactorypattern inSocketsHttpHandler.SafeProcessHandle.cs:EnsureShellExecuteFunc()lives in the OS-neutral file — the bodys_startWithShellExecute ??= StartWithShellExecuteis textually identical on both platforms; the compiler resolves the names to the platform-specific partial class members.SafeProcessHandle.Windows.cs: declaresprivate static Func<ProcessStartInfo, SafeProcessHandle>? s_startWithShellExecute— noSafeFileHandleparameters, sinceStartWithShellExecuteon Windows does not use standard I/O handles.StartCorecalls vias_startWithShellExecute!(startInfo).SafeProcessHandle.Unix.cs: declares a private custom delegateStartWithShellExecuteDelegatewith signature(ProcessStartInfo, SafeFileHandle?, SafeFileHandle?, SafeFileHandle?, out ProcessWaitState.Holder?) → SafeProcessHandle— required so theUseShellExecutepath ininternal static StartCorecorrectly flowswaitStateHolderout to theProcess.Unixcaller, preserving exit-state tracking for short-lived processes.StartWithShellExecuteoutputs the holder to the caller rather than disposing it internally; the ENOEXEC fallback path disposes the holder for the failed attempt (reusingwaitStateHolderdirectly, without an extra local) before retrying with the defaultopenhandler. The privateStartCorewrapper (used bySafeProcessHandle.Start) disposes the holder immediately after the call.ProcessStartInfo.cs:UseShellExecuteconsolidated into the shared file (previously duplicated inProcessStartInfo.Win32.csandProcessStartInfo.Unix.cs) as a property whose setter callsSafeProcessHandle.EnsureShellExecuteFunc()(using the C#fieldkeyword for the backing store).Process.Windows.cs: two redundantUseShellExecute = falseassignments removed —falseis already the default value.