Skip to content

Add Process.Start callback overload with ref struct ProcessStartArguments#128862

Draft
Copilot wants to merge 21 commits into
mainfrom
copilot/add-process-start-overload
Draft

Add Process.Start callback overload with ref struct ProcessStartArguments#128862
Copilot wants to merge 21 commits into
mainfrom
copilot/add-process-start-overload

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented Jun 1, 2026

main PR

Description

Adds Process.Start(ProcessStartInfo, Func<ProcessStartArguments, SafeProcessHandle>) to let callers create processes with custom platform APIs while still using Process infrastructure (ReadAllText, async stream handling, WaitForExit, etc.).

This PR also incorporates review feedback across the callback path and tests, including:

  • safer callback start-path handling on Unix and Windows
  • callback test coverage for both stdout and stderr content
  • Unix callback test gating for supported platforms
  • API/doc updates to match the finalized callback argument shape
  • Windows callback stderr assertion updated to match actual cmd /c echo ... 1>&2 output formatting ("error \r\n" with trailing space before \r\n)
  • Unix callback handle plumbing cleanup by removing unnecessary ToInt32() conversions and passing raw handles as nint consistently

Most notably, callback executable-path data and callback argument lifetime behavior were updated based on feedback:

  • ProcessStartArguments.FileName was replaced with Unix-only ProcessStartArguments.ResolvedPath
  • ResolvedPath is now byte* and annotated with [UnsupportedOSPlatform("windows")]
  • Unix callback test now consumes args.ResolvedPath directly for posix_spawn
  • ProcessStartArguments is now a ref struct to constrain usage to callback lifetime by construction

Latest follow-up feedback updates:

  • Unix callback path now uses Utf8StringMarshaller.ManagedToUnmanagedIn for resolved-path UTF-8 marshalling
  • Unix executable-path validation is unified without duplication via new ProcessUtils.ResolveValidPath
  • ProcessUtils.ResolvePath is now private and both Unix start paths use ResolveValidPath
  • callback path and non-callback path now share consistent null/empty-path and directory-path validation behavior
  • ProcessStartArguments XML docs were adjusted to keep summary wording generic and to describe ResolvedPath as a resolved executable path (not absolute)
  • fixed Unix callback compile failure (CS9080) by constraining marshaller lifetime with scoped and keeping stack buffer usage in the same scope

Customer Impact

Developers who need unsupported/native process creation mechanisms (for example custom CreateProcess*/posix_spawn flows) can still rely on .NET Process features instead of reimplementing process I/O and lifetime handling themselves.

Regression

No known product regression is being fixed. This is a new callback-based API path plus follow-up correctness and API-shape refinements from review feedback.

Testing

Validated with targeted builds/tests in this repo:

  • ./dotnet.sh build src/libraries/System.Diagnostics.Process/src/System.Diagnostics.Process.csproj -c Release -v minimal /t:Compile /p:TargetFramework=net11.0-linux
  • ./dotnet.sh test src/libraries/System.Diagnostics.Process/tests/System.Diagnostics.Process.Tests.csproj -c Release -f net11.0-unix -v minimal (Passed: 611, Failed: 0, Skipped: 5)

Prerequisite setup used for local test execution:

  • ./build.sh -subset clr+libs -rc Release -lc Release

Risk

Moderate. This change adds new public API surface and adjusts callback argument shape on Unix (ResolvedPath pointer) and callback-lifetime constraints (ProcessStartArguments as ref struct).
Risk is mitigated by:

  • focused changes in callback-specific paths
  • explicit API/ref/doc updates to keep surface consistent
  • unified Unix path validation logic (ResolveValidPath) to avoid divergence/duplication
  • using existing runtime marshalling primitive (Utf8StringMarshaller.ManagedToUnmanagedIn) in the callback path
  • targeted build validation and callback test updates
  • Unix handle conversion cleanup is mechanical (ToInt32() removal) and low risk
  • latest follow-up fix is narrowly scoped to marshaller lifetime/scope handling

Package authoring no longer needed in .NET 9

IMPORTANT: Starting with .NET 9, you no longer need to edit a NuGet package's csproj to enable building and bump the version.
Keep in mind that we still need package authoring in .NET 8 and older versions.

Copilot AI and others added 2 commits June 1, 2026 17:33
Introduces a new Process.Start(ProcessStartInfo, Func<ProcessStartArguments, SafeProcessHandle>)
overload that allows users to create processes using their own system calls while
leveraging .NET's Process infrastructure (pipe management, async I/O, WaitForExit).

- Added ProcessStartArguments class with platform-specific pointer properties
- Added Windows implementation using BuildCommandLine/GetEnvironmentVariablesBlock
- Added Unix implementation using ResolvePath/ParseArgv/AllocArgvArray/AllocEnvpArray
- Updated ref assembly with new public API surface
- Added Windows test using CreateProcess inside the callback
- Added Unix test using posix_spawn inside the callback

Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>
Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>
@dotnet-policy-service
Copy link
Copy Markdown
Contributor

Tagging subscribers to this area: @dotnet/area-system-diagnostics-process
See info in area-owners.md if you want to be subscribed.

- reduce code duplication
- acquire the locks!
- fix Windows tests: enable inheritance
- fix Unix implementation: handle "usesTerminal"
@adamsitnik adamsitnik force-pushed the copilot/add-process-start-overload branch from 638b886 to 3163021 Compare June 2, 2026 10:33
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds a new public Process.Start overload that prepares stdio handles + argument/environment buffers and then delegates the actual OS process creation to a user callback, returning a Process wired up to existing Process infrastructure (streams, WaitForExit, etc.).

Changes:

  • Adds new public API surface: Process.Start(ProcessStartInfo, Func<ProcessStartArguments, SafeProcessHandle>) and ProcessStartArguments.
  • Extends Windows/Unix start paths and SafeProcessHandle to support invoking a callback-based start flow.
  • Adds Windows + Unix tests exercising callback-based process creation and output redirection.

Reviewed changes

Copilot reviewed 13 out of 13 changed files in this pull request and generated 10 comments.

Show a summary per file
File Description
src/libraries/System.Diagnostics.Process/tests/ProcessHandlesTests.Windows.cs Adds a Windows test using CreateProcess inside the callback to validate stdout redirection.
src/libraries/System.Diagnostics.Process/tests/ProcessHandlesTests.Unix.cs Adds a Unix test using posix_spawn inside the callback to validate stdout redirection.
src/libraries/System.Diagnostics.Process/src/System/Diagnostics/ProcessStartArguments.cs Introduces the new argument carrier type passed to the callback.
src/libraries/System.Diagnostics.Process/src/System/Diagnostics/Process.Windows.cs Threads optional callback through the Windows StartCore flow.
src/libraries/System.Diagnostics.Process/src/System/Diagnostics/Process.Unix.cs Threads optional callback through the Unix StartCore flow and updates wait-state ownership logic.
src/libraries/System.Diagnostics.Process/src/System/Diagnostics/Process.cs Adds the new public Process.Start callback overload and refactors internal start flow.
src/libraries/System.Diagnostics.Process/src/System.Diagnostics.Process.csproj Adds the new ProcessStartArguments.cs to compilation.
src/libraries/System.Diagnostics.Process/src/Resources/Strings.resx Adds a resource string for invalid callback handle errors.
src/libraries/System.Diagnostics.Process/src/Microsoft/Win32/SafeHandles/SafeProcessHandle.Windows.cs Adds Windows callback start helper that builds/pins command line + env block and enables handle inheritance.
src/libraries/System.Diagnostics.Process/src/Microsoft/Win32/SafeHandles/SafeProcessHandle.Unix.cs Adds Unix callback start helper that allocates argv/envp and integrates wait-state registration.
src/libraries/System.Diagnostics.Process/ref/System.Diagnostics.Process.csproj Enables unsafe blocks for the ref assembly build due to pointer-typed API.
src/libraries/System.Diagnostics.Process/ref/System.Diagnostics.Process.cs Updates ref surface with new public Process.Start overload and ProcessStartArguments.
src/libraries/Common/src/Interop/Unix/System.Native/Interop.ForkAndExecProcess.cs Promotes argv/envp allocation helpers to internal for reuse.

Copy link
Copy Markdown
Member

@adamsitnik adamsitnik left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot please address my feedback

Comment thread src/libraries/System.Diagnostics.Process/tests/ProcessHandlesTests.Unix.cs Outdated
Comment thread src/libraries/System.Diagnostics.Process/tests/ProcessHandlesTests.Unix.cs Outdated
Comment thread src/libraries/System.Diagnostics.Process/tests/ProcessHandlesTests.Unix.cs Outdated
Comment thread src/libraries/System.Diagnostics.Process/tests/ProcessHandlesTests.Unix.cs Outdated
Comment thread src/libraries/System.Diagnostics.Process/tests/ProcessHandlesTests.Windows.cs Outdated
Comment thread src/libraries/System.Diagnostics.Process/tests/ProcessHandlesTests.Windows.cs Outdated
Copilot AI and others added 2 commits June 2, 2026 11:01
…local const, redirect stderr

Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>
Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>
Copilot AI requested review from Copilot and removed request for Copilot June 2, 2026 11:03
Copilot AI requested a review from adamsitnik June 2, 2026 11:04
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings June 2, 2026 14:43
Copy link
Copy Markdown
Member

@adamsitnik adamsitnik left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot address the feedback where I've tagged you

Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>
Copilot AI requested review from Copilot and removed request for Copilot June 8, 2026 10:31
Copy link
Copy Markdown
Contributor Author

Copilot AI commented Jun 8, 2026

@copilot address the feedback where I've tagged you

Addressed in f93911ac (the tagged ToInt32 feedback in SafeProcessHandle.Unix.cs is now fixed).

Copilot AI requested a review from adamsitnik June 8, 2026 10:33
Co-authored-by: Jan Kotas <jkotas@microsoft.com>
Copilot AI review requested due to automatic review settings June 8, 2026 14:26
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 13 out of 13 changed files in this pull request and generated 4 comments.

Copy link
Copy Markdown
Member

@adamsitnik adamsitnik left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot address my feedback

Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>
Copy link
Copy Markdown
Contributor Author

Copilot AI commented Jun 8, 2026

@copilot address my feedback

Addressed in 7c65489.

Copilot AI requested a review from adamsitnik June 8, 2026 16:09
Copy link
Copy Markdown
Member

@adamsitnik adamsitnik left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot fix following build failure:

src/libraries/System.Diagnostics.Process/src/Microsoft/Win32/SafeHandles/SafeProcessHandle.Unix.cs(237,70): error CS9080: (NETCORE_ENGINEERING_TELEMETRY=Build) Use of variable 'resolvedPathBuffer' in this context may expose referenced variables outside of their declaration scope

And run all tests locally before pushing changes.

Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>
Copilot AI requested review from Copilot and removed request for Copilot June 8, 2026 17:35
Copy link
Copy Markdown
Contributor Author

Copilot AI commented Jun 8, 2026

@copilot fix following build failure:

Fixed in 47c08c4d.

I addressed the CS9080 failure by making the Unix callback marshaller local scoped and keeping its stack buffer in the same declaration scope, and removed the redundant assignment that was triggering IDE0059 in that path.

Local validation run before pushing:

  • ./dotnet.sh build src/libraries/System.Diagnostics.Process/src/System.Diagnostics.Process.csproj -c Release -v minimal /t:Compile /p:TargetFramework=net11.0-linux
  • ./dotnet.sh test src/libraries/System.Diagnostics.Process/tests/System.Diagnostics.Process.Tests.csproj -c Release -f net11.0-unix -v minimal (Passed: 611, Failed: 0, Skipped: 5)

Copilot AI requested a review from adamsitnik June 8, 2026 17:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants