Skip to content

Enable StartSuspended for all Unix platforms#130347

Closed
adamsitnik with Copilot wants to merge 4 commits into
mainfrom
copilot/start-suspended-for-unixes
Closed

Enable StartSuspended for all Unix platforms#130347
adamsitnik with Copilot wants to merge 4 commits into
mainfrom
copilot/start-suspended-for-unixes

Conversation

Copilot AI commented Jul 8, 2026

Copy link
Copy Markdown
Contributor

Extends ProcessStartInfo.StartSuspended and SafeProcessHandle.Resume() to work on all Unix platforms, not just macOS. Previously these APIs threw PlatformNotSupportedException on Linux and other Unix systems.

Approved API: #94127 (comment)

Implementation approach:

  • On non-macOS Unix, the child process calls raise(SIGSTOP) before execve, suspending itself until Resume() sends SIGCONT
  • The exec-waiting pipe is closed before stopping so the parent can return the child PID without blocking
  • fork() is used instead of vfork() when startSuspended is true (child must stop before exec, incompatible with vfork's shared-memory semantics)

Changes:

  • Ref assembly: Removed [SupportedOSPlatform("windows")] / [SupportedOSPlatform("macos")] from Resume() and StartSuspended
  • SafeProcessHandle.cs: Removed platform gate and PlatformNotSupportedException from Resume()
  • ProcessStartInfo.cs: Removed [SupportedOSPlatform] attributes and platform validation check
  • pal_process.c: Removed ENOTSUP early-return; added fork-over-vfork selection when suspended; added pipe-close + raise(SIGSTOP) before execve
  • Tests: Removed [PlatformSpecific] restriction and the StartSuspendedTests_NonWindowsNonMacOS class that tested the now-removed exception

- Remove [SupportedOSPlatform] attributes from StartSuspended and Resume()
- Remove platform check in SafeProcessHandle.Resume() and ProcessStartInfo validation
- In native pal_process.c: remove ENOTSUP check, use fork() instead of vfork()
  when startSuspended is true, and raise(SIGSTOP) before execve
- Close the exec-waiting pipe before SIGSTOP so parent can proceed
- Update tests: remove PlatformSpecific attribute and non-supported test class

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.

@adamsitnik
adamsitnik requested a review from Copilot July 8, 2026 11:16
Copilot AI had a problem deploying to copilot-pat-pool July 8, 2026 11:16 Failure
Copilot AI had a problem deploying to copilot-pat-pool July 8, 2026 11:17 Failure
@adamsitnik adamsitnik added this to the 11.0.0 milestone Jul 8, 2026

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 expands ProcessStartInfo.StartSuspended and SafeProcessHandle.Resume() beyond macOS by implementing “start suspended” on non-macOS Unix using a pre-execve self-stop (SIGSTOP) and resuming via SIGCONT, and updates the public contract/tests accordingly.

Changes:

  • Updates native Unix process creation to support startSuspended in the fork/exec path (including fork-over-vfork selection).
  • Removes platform gating/attributes so StartSuspended / Resume() are no longer limited to Windows+macOS.
  • Broadens the existing StartSuspended test coverage beyond Windows/macOS and removes now-obsolete “throws PNSE” tests.

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
src/native/libs/System.Native/pal_process.c Implements non-macOS Unix StartSuspended via SIGSTOP before execve and switches to fork() when suspended.
src/libraries/System.Diagnostics.Process/tests/StartSuspendedTests.cs Removes Windows/macOS-only restriction and deletes tests expecting PNSE on other Unix OSes.
src/libraries/System.Diagnostics.Process/src/System/Diagnostics/ProcessStartInfo.cs Updates docs and removes runtime platform validation for StartSuspended.
src/libraries/System.Diagnostics.Process/src/Microsoft/Win32/SafeHandles/SafeProcessHandle.cs Removes platform gate/PNSE from Resume() and updates remarks to “Unix”.
src/libraries/System.Diagnostics.Process/ref/System.Diagnostics.Process.cs Updates ref contract by removing Windows/macOS-only platform annotations for Resume() and StartSuspended.

Comment thread src/native/libs/System.Native/pal_process.c

@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 the feedback

Comment thread src/native/libs/System.Native/pal_process.c
…, immediate-resume test

- pal_process.c: add waitpid(WUNTRACED) in parent after pipe close for
  startSuspended to eliminate SIGCONT/SIGSTOP race condition
- ProcessStartInfo.cs: clarify in docs that on non-macOS Unix suspension
  occurs before execve (process image not yet replaced)
- StartSuspendedTests.cs: add StartSuspended_ResumeImmediately_Succeeds
  test that starts suspended and immediately calls Resume

Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>
Copilot AI requested review from Copilot and removed request for Copilot July 8, 2026 12:03
- Remove redundant processId > 0 guard (success implies positive PID)
- Separate WIFEXITED/WIFSIGNALED cases with clearer ECHILD error and comment

Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>
Copilot AI requested review from adamsitnik and Copilot and removed request for Copilot July 8, 2026 12:06
@adamsitnik
adamsitnik requested a review from Copilot July 8, 2026 13:41
Copilot AI had a problem deploying to copilot-pat-pool July 8, 2026 13:42 Failure

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 5 out of 5 changed files in this pull request and generated 1 comment.

Comment thread src/native/libs/System.Native/pal_process.c
@adamsitnik
adamsitnik marked this pull request as ready for review July 8, 2026 13:59

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

LGTM, @copilot please apply my suggestion

Comment thread src/libraries/System.Diagnostics.Process/tests/StartSuspendedTests.cs Outdated
…ucceeds test

Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>
Copilot AI requested review from Copilot and removed request for Copilot July 8, 2026 14:09
Copilot AI requested a review from adamsitnik July 8, 2026 14:09
Copilot AI had a problem deploying to copilot-pat-pool July 8, 2026 14:10 Failure

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

It LGTM!

@tmds could you please review it? So far we got the Windows and macOS (#129570) implementations merged, where this is a native concept.

@tmds

tmds commented Jul 13, 2026

Copy link
Copy Markdown
Member

@adamsitnik does this suspend implementation make sense? Are the semantics sufficiently similar to Windows? You are between fork and exec, so what is suspended is not the actual process.

@adamsitnik

Copy link
Copy Markdown
Member

@adamsitnik does this suspend implementation make sense? Are the semantics sufficiently similar to Windows? You are between fork and exec, so what is suspended is not the actual process.

My goal is to make it as close as possible to POSIX_SPAWN_START_SUSPENDED (macOS). From https://keith.github.io/xcode-man-pages/posix_spawnattr_setflags.3.html:

POSIX_SPAWN_START_SUSPENDED: If this bit is set, then the child process will be created as if it immediately received a SIGSTOP signal, permitting debuggers, profilers, and other programs to manipulate the process before it begins execution in user space. This permits, for example, obtaining exact instruction counts, or debugging very early in dyld(1). To resume the child process, it must be sent a SIGCONT signal.

We suspend the process via SIGSTOP before any user code executes. The provided PID is also valid. SIGCONT is used to resume.

@tmds do you see any scenarios where it would fail?

@tmds

tmds commented Jul 13, 2026

Copy link
Copy Markdown
Member

The implementation looks mechanically correct, but I think what it ends up doing may not enable the same things as it does on Windows and macOS.

For example, if you'd attach a debugger on this suspended process, the target is not the application you want to debug. You can't set breakpoints, etc.

So my question is whether this enables what the users of the API are likely expecting.

@tmds

tmds commented Jul 15, 2026

Copy link
Copy Markdown
Member

My goal is to make it as close as possible to POSIX_SPAWN_START_SUSPENDED (macOS).

This one suspends after the exec, which is a major difference with what this implementation does.

To implement this on Linux, it seems we can use PTRACE_TRACEME (see https://man7.org/linux/man-pages/man2/ptrace.2.html).

@adamsitnik

Copy link
Copy Markdown
Member

This one suspends after the exec, which is a major difference with what this implementation does.

I agree.

To implement this on Linux, it seems we can use PTRACE_TRACEME (see https://man7.org/linux/man-pages/man2/ptrace.2.html).

But this would have some side effects that could also be not expected.

I think I am going to close this PR as of now and simply wait for more user feedback. Perhaps people would be happy with what I am suggesting here or PTRACE_TRACEME would be better.

@MattParkerDev

Copy link
Copy Markdown

Why not use posix_spawn on Linux too?

@MichalPetryka

Copy link
Copy Markdown
Contributor

Why not use posix_spawn on Linux too?

As per google AI: POSIX_SPAWN_START_SUSPENDED is an Apple-specific extension to the POSIX spawn API, supported on macOS, iOS, and other Darwin-based platforms.

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.

6 participants