Skip to content

Add Process.Start callback overload with WindowsProcessStartArguments and UnixProcessStartArguments#128862

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

Add Process.Start callback overload with WindowsProcessStartArguments and UnixProcessStartArguments#128862
Copilot wants to merge 26 commits into
mainfrom
copilot/add-process-start-overload

Conversation

Copilot AI commented Jun 1, 2026

Copy link
Copy Markdown
Contributor

main PR

Description

Adds WindowsProcessStartArguments.Start(ProcessStartInfo, Func<WindowsProcessStartArguments, SafeProcessHandle>) and UnixProcessStartArguments.Start(ProcessStartInfo, Func<UnixProcessStartArguments, SafeProcessHandle>) in the System.Runtime.InteropServices namespace to let callers create processes with custom platform APIs while still using Process infrastructure (ReadAllText, async stream handling, WaitForExit, etc.).

The two new ref struct types — WindowsProcessStartArguments and UnixProcessStartArguments — carry the prepared start data (standard handles, command line/argv, environment block, and on Unix the resolved executable path as a UTF-8 pointer) into the caller-supplied callback. The ref struct constraint ties the lifetime of pointer-typed properties to the callback invocation.

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
  • both new types moved to System.Runtime.InteropServices namespace
  • [SupportedOSPlatform("windows")] added to WindowsProcessStartArguments implementation and [UnsupportedOSPlatform("windows")] added to UnixProcessStartArguments implementation to match the ref assembly
  • misleading "writable" remark removed from UnixProcessStartArguments.ResolvedPath docs (setter is internal)
  • ProcessUtils.ResolveValidPath now normalizes empty workingDirectory to null for consistent error messages
  • spurious [CLSCompliant(false)] removed from Process.Start(string) in the ref assembly

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

  • the original ProcessStartArguments.FileName was replaced with Unix-only UnixProcessStartArguments.ResolvedPath
  • ResolvedPath is byte* and annotated with [UnsupportedOSPlatform("windows")]
  • Unix callback test consumes args.ResolvedPath directly for posix_spawn

Latest follow-up feedback updates:

  • Unix callback path uses Utf8StringMarshaller.ManagedToUnmanagedIn for resolved-path UTF-8 marshalling
  • Unix executable-path validation is unified without duplication via ProcessUtils.ResolveValidPath
  • ProcessUtils.ResolvePath is private and both Unix start paths use ResolveValidPath
  • callback path and non-callback path share consistent null/empty-path and directory-path validation behavior

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 in System.Runtime.InteropServices (WindowsProcessStartArguments and UnixProcessStartArguments) and adjusts callback argument shape on Unix (ResolvedPath pointer) and callback-lifetime constraints (ref struct).
Risk is mitigated by:

  • focused changes in callback-specific paths
  • explicit API/ref/doc updates to keep surface consistent between implementation and ref assembly
  • 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

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>
- 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

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

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.

Comment thread src/libraries/System.Diagnostics.Process/src/System/Diagnostics/Process.cs Outdated

@adamsitnik adamsitnik left a comment

Copy link
Copy Markdown
Member

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
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

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.

Comment thread src/libraries/System.Diagnostics.Process/src/System/Diagnostics/Process.cs Outdated

@adamsitnik adamsitnik left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

@copilot address my feedback

Comment thread src/libraries/System.Diagnostics.Process/src/System/Diagnostics/Process.cs Outdated
Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>

Copilot AI commented Jun 8, 2026

Copy link
Copy Markdown
Contributor Author

@copilot address my feedback

Addressed in 7c65489.

Copilot AI requested a review from adamsitnik June 8, 2026 16:09

@adamsitnik adamsitnik left a comment

Copy link
Copy Markdown
Member

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

Copilot AI commented Jun 8, 2026

Copy link
Copy Markdown
Contributor Author

@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
Copilot AI review requested due to automatic review settings June 17, 2026 18:54

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

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 15 out of 15 changed files in this pull request and generated 7 comments.

Comments suppressed due to low confidence (1)

src/libraries/System.Diagnostics.Process/ref/System.Diagnostics.Process.cs:222

  • The newly added [CLSCompliant(false)] attribute is applied to Process.Start(string fileName), but the implementation method is not marked CLS-noncompliant and the signature is CLS-compliant. This creates ref/runtime metadata mismatch and changes the public contract for an existing API.
        [System.CLSCompliantAttribute(false)]
        [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("ios")]
        [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("tvos")]
        [System.Runtime.Versioning.SupportedOSPlatformAttribute("maccatalyst")] // this needs to come after the ios attribute due to limitations in the platform analyzer
        public static System.Diagnostics.Process Start(string fileName) { throw null; }

Comment thread src/libraries/System.Diagnostics.Process/ref/System.Diagnostics.Process.cs Outdated
Comment thread src/libraries/System.Diagnostics.Process/ref/System.Diagnostics.Process.cs Outdated

@adamsitnik adamsitnik left a comment

Copy link
Copy Markdown
Member

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/ref/System.Diagnostics.Process.cs Outdated
Comment thread src/libraries/System.Diagnostics.Process/ref/System.Diagnostics.Process.cs Outdated
Comment thread src/libraries/System.Diagnostics.Process/ref/System.Diagnostics.Process.cs Outdated
Copilot AI and others added 2 commits June 18, 2026 11:58
…form attrs, cwd normalization

Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

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 15 out of 15 changed files in this pull request and generated 7 comments.

@adamsitnik adamsitnik left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

@copilot address feedback

Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>

Copilot AI commented Jun 18, 2026

Copy link
Copy Markdown
Contributor Author

@copilot address feedback

Addressed in c1824bb.

/// A function that receives the prepared <see cref="UnixProcessStartArguments"/> and creates the process using any system call of the user's choice.
/// The callback must return a valid <see cref="SafeProcessHandle"/> for the newly created process.
/// The memory referenced by pointer properties in <see cref="UnixProcessStartArguments"/> is only valid for the duration of the callback.
/// The callback is invoked while an internal process-start lock is held; calling APIs that start processes from within the callback may deadlock or throw.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Suggested change
/// The callback is invoked while an internal process-start lock is held; calling APIs that start processes from within the callback may deadlock or throw.
/// The callback is invoked while an internal process-start lock is held; calling System.Diagnostic.Process APIs that start processes from within the callback may deadlock or throw.

Be specific that this applies to S.D.Process APIs only. Calling OS APIs that start new processes is fine and actually required.

(Fix this for both versions of OS process start arguments.)

@copilot

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Updated in c152ec2. I narrowed the lock warning in both UnixProcessStartArguments and WindowsProcessStartArguments to explicitly call out only System.Diagnostics.Process APIs that start processes; OS process-start APIs remain valid for the callback scenario.

Co-authored-by: jkotas <6668460+jkotas@users.noreply.github.com>
}

// Get SafeProcessHandle from the pid.
// In the future, SafeProcessHandle.Open will be used instead.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Can we use it now?

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.

[API Proposal]: Process constructor from SafeProcessHandle

4 participants