Implement Process.Run, RunAsync, RunAndCaptureText, RunAndCaptureTextAsync APIs - #127210

Merged
adamsitnik merged 32 commits into
mainfrom
copilot/implement-process-run-apis
Apr 22, 2026
Merged

Implement Process.Run, RunAsync, RunAndCaptureText, RunAndCaptureTextAsync APIs#127210
adamsitnik merged 32 commits into
mainfrom
copilot/implement-process-run-apis

Conversation

CopilotAI commented Apr 21, 2026

Copy link
Copy Markdown
Contributor
  • Rebase onto main after base branch copilot/implement-issue-126293 was merged into main as PR Implement SafeProcessHandle.WaitForExit* methods #127022
  • Implement Process.Run, RunAsync, RunAndCaptureText, RunAndCaptureTextAsync APIs
  • RunAndCapture* PSI overloads require RedirectStandardOutput/Error to be enabled (no PSI mutation)
  • String overloads use CreateStartInfoForCapture helper that sets redirect flags
  • RunAsync/RunAndCaptureTextAsync always use WaitForExitOrKillOnCancellationAsync (CanBeCanceled check is already inside that method)
  • Comprehensive test coverage for all API parameters and permutations using [Theory]
  • Tests cover: Run (PSI, PSI+timeout, fileName, fileName+timeout/cancel), RunAndCaptureText (PSI, PSI+timeout, fileName, fileName+timeout/cancel), argument validation, UseShellExecute rejection, NotRedirected rejection
  • All 40 RunTests and 10 StartAndForgetTests pass

CopilotAIand others added 21 commits April 16, 2026 09:51
- Add WaitForExit, TryWaitForExit, WaitForExitOrKillOnTimeout,
WaitForExitAsync, WaitForExitOrKillOnCancellationAsync to
SafeProcessHandle
- Windows: uses ProcessWaitHandle + GetExitCodeProcess
- Unix: integrates with ProcessWaitState for reaping coordination
- Native: WaitPidExitedNoHang now returns terminating signal info
- ProcessWaitState: tracks terminating signal for ProcessExitStatus
- Ref assembly: updated with new API surface
- Tests: added comprehensive WaitForExit* tests
Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/3540beba-26c4-4014-b276-d6fa244eda82
Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>
…e ToTimeoutMilliseconds to ProcessUtils, remove KillCore, fix platform attributes, update native PAL
- ProcessWaitState: store ProcessExitStatus? instead of separate _exitCode/_terminatingSignal
- Native PAL: use TryConvertSignalCodeToPosixSignal for proper PosixSignal mapping
- Move ToTimeoutMilliseconds to ProcessUtils.cs, reuse from Process and SafeProcessHandle
- Remove separate KillCore methods on both platforms; use SignalCore on Unix, TerminateProcessCore on Windows
- Remove platform attributes from WaitForExit, TryWaitForExit, WaitForExitAsync (non-killing methods)
- Fix CreateExitStatus canceled logic: canceled && signal is not null
- Update Process.Unix.cs to consume ProcessExitStatus? from GetExited
Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/1a601c8b-3c5f-4596-9b8f-5e11188e35ae
Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>
… pragma, simplify Unix async via ProcessWaitState.WaitForExitAsync, add PlatformNotSupportedException checks, rename wasKilled to signalWasSent, add Debug.Assert, update ProcessHandlesTests.Windows.cs
Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/603f063f-b34a-42f8-ab6b-e1aa2df62675
Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>
- there is no need to start suspended process anymore, as we can wait on the handle to exit directly
- revert changes I did not like
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
…tests
- Fix GetWaitState() on Unix to lazily initialize _waitState from ProcessWaitState table
so that SafeProcessHandle from Process.SafeHandle works for WaitForExit*
- Add _lazyWaitStateHolder field to properly manage ref count lifecycle
- Convert signal test from Fact to Theory with SIGKILL and SIGTERM
- Add Process.SafeHandle WaitForExit* tests to ProcessWaitingTests
Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/52916352-c074-4483-8dca-72cf3696462e
Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>
…, rename test methods
Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/52916352-c074-4483-8dca-72cf3696462e
Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>
- Use WaitInMS timeout at line 55 per reviewer suggestion
- Merge two WaitForExit_ProcessExitsNormally tests into one
- Merge sync/async WaitForExit into theory with bool useAsync
- Merge sync/async WaitForExitOrKill normal-exit into theory
- Merge sync/async WaitForExitOrKill timeout/cancel into theory
Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/3a1553e0-3850-4588-b95f-5452296a0275
Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>
…ocessId) matching Process pattern
Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/3f4f9d58-e237-49c2-9220-e41731a20fde
Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>
…e lazy init
All SafeProcessHandle instances are now created with a ProcessWaitState:
- Added Holder(Holder) copy constructor to ProcessWaitState.Holder
- Added IncrementRefCount() to ProcessWaitState for ref counting
- SafeProcessHandle now owns its own Holder copy (disposed in ReleaseHandle)
- Made _waitState readonly, removed _lazyWaitStateHolder and EnsureWaitStateInitialized
- Updated GetProcessHandle() in Process.Unix.cs to pass Holder when creating SafeProcessHandle
Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/a866727c-2478-4cdc-a3ec-6ce0e20f929e
Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
…-child process on Unix
Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/fb9ffb85-16b8-436b-b588-0f5527b85606
Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>
…Async APIs
Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/6d89c552-8d80-40db-bf17-c2f9effc55ca
Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>

@adamsitnikadamsitnik 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 threadsrc/libraries/System.Diagnostics.Process/tests/RunTests.cs Outdated
@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.

…elpers, fix timeout tracking, reuse MapToArgumentList
Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/840381dc-b4f5-46ce-a7ed-bdde61b0ca90
Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>

CopilotAI commented Apr 21, 2026

Copy link
Copy Markdown
ContributorAuthor

@copilot address my feedback

All feedback addressed in bbb0c70. All 30 RunTests and 10 StartAndForgetTests pass.

CopilotAIand others added 4 commits April 21, 2026 21:56
…lOnCancellationAsync
Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/73a14058-c419-4277-b5e2-885c9c6c8607
Co-authored-by: danmoseley <6385855+danmoseley@users.noreply.github.com>

CopilotAI commented Apr 21, 2026

Copy link
Copy Markdown
ContributorAuthor

@copilot please look at afeedback and address as appropriate. use one separate commit for each piece of feedback.

All feedback addressed in separate commits:

  • fc2f007 — require RedirectStandard* on PSI overloads instead of mutating
  • 391c3c4 — simplify async methods by always using WaitForExitOrKillOnCancellationAsync
  • f78f6dc — audit and improve test coverage
  • c15a6ef — fix CancellationTokenSource leaks in tests

All 40 RunTests and 10 StartAndForgetTests pass.

Base automatically changed from copilot/implement-issue-126293 to mainApril 22, 2026 03:31
CopilotAIand others added 2 commits April 22, 2026 04:13
…Async APIs
- Run/RunAsync: synchronously/asynchronously starts a process, waits for exit, returns ProcessExitStatus
- RunAndCaptureText/RunAndCaptureTextAsync: starts a process, captures stdout/stderr, returns ProcessTextOutput
- PSI overloads for RunAndCapture* require RedirectStandardOutput and RedirectStandardError to be enabled
- String overloads use CreateStartInfoForCapture helper to set redirect flags
- All async methods always use WaitForExitOrKillOnCancellationAsync
- Comprehensive tests for all API parameters and permutations
Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>
Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>
CopilotAI requested review from Copilot and removed request for CopilotApril 22, 2026 04:16
@adamsitnik
adamsitnik enabled auto-merge (squash) April 22, 2026 04:43
@adamsitnik

Copy link
Copy Markdown
Member

/ba-g the linux x64 timeouts are hunting all opened PRs, I believe it's unrelated. I've run it locally to confirm the Process tests are passing on x64
{2AB65DDF-C9E1-46A6-A21F-03F9CB29A706}

@adamsitnik
adamsitnik merged commit b54e86d into mainApr 22, 2026
82 of 97 checks passed
@adamsitnik
adamsitnik deleted the copilot/implement-process-run-apis branch April 22, 2026 10:44
@github-actionsgithub-actionsBot locked and limited conversation to collaborators May 24, 2026
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants

@danmoseley@adamsitnik@jkotas
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

Implement Process.Run, RunAsync, RunAndCaptureText, RunAndCaptureTextAsync APIs - #127210

Merged
adamsitnik merged 32 commits into
mainfrom
copilot/implement-process-run-apis
Apr 22, 2026
Merged

Implement Process.Run, RunAsync, RunAndCaptureText, RunAndCaptureTextAsync APIs#127210
adamsitnik merged 32 commits into
mainfrom
copilot/implement-process-run-apis

Conversation

CopilotAI commented Apr 21, 2026

Copy link
Copy Markdown
Contributor
  • Rebase onto main after base branch copilot/implement-issue-126293 was merged into main as PR Implement SafeProcessHandle.WaitForExit* methods #127022
  • Implement Process.Run, RunAsync, RunAndCaptureText, RunAndCaptureTextAsync APIs
  • RunAndCapture* PSI overloads require RedirectStandardOutput/Error to be enabled (no PSI mutation)
  • String overloads use CreateStartInfoForCapture helper that sets redirect flags
  • RunAsync/RunAndCaptureTextAsync always use WaitForExitOrKillOnCancellationAsync (CanBeCanceled check is already inside that method)
  • Comprehensive test coverage for all API parameters and permutations using [Theory]
  • Tests cover: Run (PSI, PSI+timeout, fileName, fileName+timeout/cancel), RunAndCaptureText (PSI, PSI+timeout, fileName, fileName+timeout/cancel), argument validation, UseShellExecute rejection, NotRedirected rejection
  • All 40 RunTests and 10 StartAndForgetTests pass

CopilotAIand others added 21 commits April 16, 2026 09:51
- Add WaitForExit, TryWaitForExit, WaitForExitOrKillOnTimeout,
WaitForExitAsync, WaitForExitOrKillOnCancellationAsync to
SafeProcessHandle
- Windows: uses ProcessWaitHandle + GetExitCodeProcess
- Unix: integrates with ProcessWaitState for reaping coordination
- Native: WaitPidExitedNoHang now returns terminating signal info
- ProcessWaitState: tracks terminating signal for ProcessExitStatus
- Ref assembly: updated with new API surface
- Tests: added comprehensive WaitForExit* tests
Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/3540beba-26c4-4014-b276-d6fa244eda82
Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>
…e ToTimeoutMilliseconds to ProcessUtils, remove KillCore, fix platform attributes, update native PAL
- ProcessWaitState: store ProcessExitStatus? instead of separate _exitCode/_terminatingSignal
- Native PAL: use TryConvertSignalCodeToPosixSignal for proper PosixSignal mapping
- Move ToTimeoutMilliseconds to ProcessUtils.cs, reuse from Process and SafeProcessHandle
- Remove separate KillCore methods on both platforms; use SignalCore on Unix, TerminateProcessCore on Windows
- Remove platform attributes from WaitForExit, TryWaitForExit, WaitForExitAsync (non-killing methods)
- Fix CreateExitStatus canceled logic: canceled && signal is not null
- Update Process.Unix.cs to consume ProcessExitStatus? from GetExited
Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/1a601c8b-3c5f-4596-9b8f-5e11188e35ae
Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>
… pragma, simplify Unix async via ProcessWaitState.WaitForExitAsync, add PlatformNotSupportedException checks, rename wasKilled to signalWasSent, add Debug.Assert, update ProcessHandlesTests.Windows.cs
Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/603f063f-b34a-42f8-ab6b-e1aa2df62675
Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>
- there is no need to start suspended process anymore, as we can wait on the handle to exit directly
- revert changes I did not like
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
…tests
- Fix GetWaitState() on Unix to lazily initialize _waitState from ProcessWaitState table
so that SafeProcessHandle from Process.SafeHandle works for WaitForExit*
- Add _lazyWaitStateHolder field to properly manage ref count lifecycle
- Convert signal test from Fact to Theory with SIGKILL and SIGTERM
- Add Process.SafeHandle WaitForExit* tests to ProcessWaitingTests
Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/52916352-c074-4483-8dca-72cf3696462e
Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>
…, rename test methods
Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/52916352-c074-4483-8dca-72cf3696462e
Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>
- Use WaitInMS timeout at line 55 per reviewer suggestion
- Merge two WaitForExit_ProcessExitsNormally tests into one
- Merge sync/async WaitForExit into theory with bool useAsync
- Merge sync/async WaitForExitOrKill normal-exit into theory
- Merge sync/async WaitForExitOrKill timeout/cancel into theory
Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/3a1553e0-3850-4588-b95f-5452296a0275
Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>
…ocessId) matching Process pattern
Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/3f4f9d58-e237-49c2-9220-e41731a20fde
Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>
…e lazy init
All SafeProcessHandle instances are now created with a ProcessWaitState:
- Added Holder(Holder) copy constructor to ProcessWaitState.Holder
- Added IncrementRefCount() to ProcessWaitState for ref counting
- SafeProcessHandle now owns its own Holder copy (disposed in ReleaseHandle)
- Made _waitState readonly, removed _lazyWaitStateHolder and EnsureWaitStateInitialized
- Updated GetProcessHandle() in Process.Unix.cs to pass Holder when creating SafeProcessHandle
Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/a866727c-2478-4cdc-a3ec-6ce0e20f929e
Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
…-child process on Unix
Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/fb9ffb85-16b8-436b-b588-0f5527b85606
Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>
…Async APIs
Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/6d89c552-8d80-40db-bf17-c2f9effc55ca
Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>

@adamsitnikadamsitnik 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 threadsrc/libraries/System.Diagnostics.Process/tests/RunTests.cs Outdated
@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.

…elpers, fix timeout tracking, reuse MapToArgumentList
Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/840381dc-b4f5-46ce-a7ed-bdde61b0ca90
Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>

CopilotAI commented Apr 21, 2026

Copy link
Copy Markdown
ContributorAuthor

@copilot address my feedback

All feedback addressed in bbb0c70. All 30 RunTests and 10 StartAndForgetTests pass.

CopilotAIand others added 4 commits April 21, 2026 21:56
…lOnCancellationAsync
Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/73a14058-c419-4277-b5e2-885c9c6c8607
Co-authored-by: danmoseley <6385855+danmoseley@users.noreply.github.com>

CopilotAI commented Apr 21, 2026

Copy link
Copy Markdown
ContributorAuthor

@copilot please look at afeedback and address as appropriate. use one separate commit for each piece of feedback.

All feedback addressed in separate commits:

  • fc2f007 — require RedirectStandard* on PSI overloads instead of mutating
  • 391c3c4 — simplify async methods by always using WaitForExitOrKillOnCancellationAsync
  • f78f6dc — audit and improve test coverage
  • c15a6ef — fix CancellationTokenSource leaks in tests

All 40 RunTests and 10 StartAndForgetTests pass.

Base automatically changed from copilot/implement-issue-126293 to mainApril 22, 2026 03:31
CopilotAIand others added 2 commits April 22, 2026 04:13
…Async APIs
- Run/RunAsync: synchronously/asynchronously starts a process, waits for exit, returns ProcessExitStatus
- RunAndCaptureText/RunAndCaptureTextAsync: starts a process, captures stdout/stderr, returns ProcessTextOutput
- PSI overloads for RunAndCapture* require RedirectStandardOutput and RedirectStandardError to be enabled
- String overloads use CreateStartInfoForCapture helper to set redirect flags
- All async methods always use WaitForExitOrKillOnCancellationAsync
- Comprehensive tests for all API parameters and permutations
Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>
Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>
CopilotAI requested review from Copilot and removed request for CopilotApril 22, 2026 04:16
@adamsitnik
adamsitnik enabled auto-merge (squash) April 22, 2026 04:43
@adamsitnik

Copy link
Copy Markdown
Member

/ba-g the linux x64 timeouts are hunting all opened PRs, I believe it's unrelated. I've run it locally to confirm the Process tests are passing on x64
{2AB65DDF-C9E1-46A6-A21F-03F9CB29A706}

@adamsitnik
adamsitnik merged commit b54e86d into mainApr 22, 2026
82 of 97 checks passed
@adamsitnik
adamsitnik deleted the copilot/implement-process-run-apis branch April 22, 2026 10:44
@github-actionsgithub-actionsBot locked and limited conversation to collaborators May 24, 2026
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants

@danmoseley@adamsitnik@jkotas
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Implement Process.Run, RunAsync, RunAndCaptureText, RunAndCaptureTextAsync APIs - #127210

Merged
adamsitnik merged 32 commits into
mainfrom
copilot/implement-process-run-apis
Apr 22, 2026
Merged

Implement Process.Run, RunAsync, RunAndCaptureText, RunAndCaptureTextAsync APIs#127210
adamsitnik merged 32 commits into
mainfrom
copilot/implement-process-run-apis

Conversation

CopilotAI commented Apr 21, 2026

Copy link
Copy Markdown
Contributor
  • Rebase onto main after base branch copilot/implement-issue-126293 was merged into main as PR Implement SafeProcessHandle.WaitForExit* methods #127022
  • Implement Process.Run, RunAsync, RunAndCaptureText, RunAndCaptureTextAsync APIs
  • RunAndCapture* PSI overloads require RedirectStandardOutput/Error to be enabled (no PSI mutation)
  • String overloads use CreateStartInfoForCapture helper that sets redirect flags
  • RunAsync/RunAndCaptureTextAsync always use WaitForExitOrKillOnCancellationAsync (CanBeCanceled check is already inside that method)
  • Comprehensive test coverage for all API parameters and permutations using [Theory]
  • Tests cover: Run (PSI, PSI+timeout, fileName, fileName+timeout/cancel), RunAndCaptureText (PSI, PSI+timeout, fileName, fileName+timeout/cancel), argument validation, UseShellExecute rejection, NotRedirected rejection
  • All 40 RunTests and 10 StartAndForgetTests pass

CopilotAIand others added 21 commits April 16, 2026 09:51
- Add WaitForExit, TryWaitForExit, WaitForExitOrKillOnTimeout,
WaitForExitAsync, WaitForExitOrKillOnCancellationAsync to
SafeProcessHandle
- Windows: uses ProcessWaitHandle + GetExitCodeProcess
- Unix: integrates with ProcessWaitState for reaping coordination
- Native: WaitPidExitedNoHang now returns terminating signal info
- ProcessWaitState: tracks terminating signal for ProcessExitStatus
- Ref assembly: updated with new API surface
- Tests: added comprehensive WaitForExit* tests
Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/3540beba-26c4-4014-b276-d6fa244eda82
Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>
…e ToTimeoutMilliseconds to ProcessUtils, remove KillCore, fix platform attributes, update native PAL
- ProcessWaitState: store ProcessExitStatus? instead of separate _exitCode/_terminatingSignal
- Native PAL: use TryConvertSignalCodeToPosixSignal for proper PosixSignal mapping
- Move ToTimeoutMilliseconds to ProcessUtils.cs, reuse from Process and SafeProcessHandle
- Remove separate KillCore methods on both platforms; use SignalCore on Unix, TerminateProcessCore on Windows
- Remove platform attributes from WaitForExit, TryWaitForExit, WaitForExitAsync (non-killing methods)
- Fix CreateExitStatus canceled logic: canceled && signal is not null
- Update Process.Unix.cs to consume ProcessExitStatus? from GetExited
Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/1a601c8b-3c5f-4596-9b8f-5e11188e35ae
Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>
… pragma, simplify Unix async via ProcessWaitState.WaitForExitAsync, add PlatformNotSupportedException checks, rename wasKilled to signalWasSent, add Debug.Assert, update ProcessHandlesTests.Windows.cs
Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/603f063f-b34a-42f8-ab6b-e1aa2df62675
Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>
- there is no need to start suspended process anymore, as we can wait on the handle to exit directly
- revert changes I did not like
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
…tests
- Fix GetWaitState() on Unix to lazily initialize _waitState from ProcessWaitState table
so that SafeProcessHandle from Process.SafeHandle works for WaitForExit*
- Add _lazyWaitStateHolder field to properly manage ref count lifecycle
- Convert signal test from Fact to Theory with SIGKILL and SIGTERM
- Add Process.SafeHandle WaitForExit* tests to ProcessWaitingTests
Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/52916352-c074-4483-8dca-72cf3696462e
Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>
…, rename test methods
Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/52916352-c074-4483-8dca-72cf3696462e
Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>
- Use WaitInMS timeout at line 55 per reviewer suggestion
- Merge two WaitForExit_ProcessExitsNormally tests into one
- Merge sync/async WaitForExit into theory with bool useAsync
- Merge sync/async WaitForExitOrKill normal-exit into theory
- Merge sync/async WaitForExitOrKill timeout/cancel into theory
Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/3a1553e0-3850-4588-b95f-5452296a0275
Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>
…ocessId) matching Process pattern
Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/3f4f9d58-e237-49c2-9220-e41731a20fde
Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>
…e lazy init
All SafeProcessHandle instances are now created with a ProcessWaitState:
- Added Holder(Holder) copy constructor to ProcessWaitState.Holder
- Added IncrementRefCount() to ProcessWaitState for ref counting
- SafeProcessHandle now owns its own Holder copy (disposed in ReleaseHandle)
- Made _waitState readonly, removed _lazyWaitStateHolder and EnsureWaitStateInitialized
- Updated GetProcessHandle() in Process.Unix.cs to pass Holder when creating SafeProcessHandle
Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/a866727c-2478-4cdc-a3ec-6ce0e20f929e
Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
…-child process on Unix
Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/fb9ffb85-16b8-436b-b588-0f5527b85606
Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>
…Async APIs
Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/6d89c552-8d80-40db-bf17-c2f9effc55ca
Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>

@adamsitnikadamsitnik 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 threadsrc/libraries/System.Diagnostics.Process/tests/RunTests.cs Outdated
@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.

…elpers, fix timeout tracking, reuse MapToArgumentList
Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/840381dc-b4f5-46ce-a7ed-bdde61b0ca90
Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>

CopilotAI commented Apr 21, 2026

Copy link
Copy Markdown
ContributorAuthor

@copilot address my feedback

All feedback addressed in bbb0c70. All 30 RunTests and 10 StartAndForgetTests pass.

CopilotAIand others added 4 commits April 21, 2026 21:56
…lOnCancellationAsync
Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/73a14058-c419-4277-b5e2-885c9c6c8607
Co-authored-by: danmoseley <6385855+danmoseley@users.noreply.github.com>

CopilotAI commented Apr 21, 2026

Copy link
Copy Markdown
ContributorAuthor

@copilot please look at afeedback and address as appropriate. use one separate commit for each piece of feedback.

All feedback addressed in separate commits:

  • fc2f007 — require RedirectStandard* on PSI overloads instead of mutating
  • 391c3c4 — simplify async methods by always using WaitForExitOrKillOnCancellationAsync
  • f78f6dc — audit and improve test coverage
  • c15a6ef — fix CancellationTokenSource leaks in tests

All 40 RunTests and 10 StartAndForgetTests pass.

Base automatically changed from copilot/implement-issue-126293 to mainApril 22, 2026 03:31
CopilotAIand others added 2 commits April 22, 2026 04:13
…Async APIs
- Run/RunAsync: synchronously/asynchronously starts a process, waits for exit, returns ProcessExitStatus
- RunAndCaptureText/RunAndCaptureTextAsync: starts a process, captures stdout/stderr, returns ProcessTextOutput
- PSI overloads for RunAndCapture* require RedirectStandardOutput and RedirectStandardError to be enabled
- String overloads use CreateStartInfoForCapture helper to set redirect flags
- All async methods always use WaitForExitOrKillOnCancellationAsync
- Comprehensive tests for all API parameters and permutations
Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>
Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>
CopilotAI requested review from Copilot and removed request for CopilotApril 22, 2026 04:16
@adamsitnik
adamsitnik enabled auto-merge (squash) April 22, 2026 04:43
@adamsitnik

Copy link
Copy Markdown
Member

/ba-g the linux x64 timeouts are hunting all opened PRs, I believe it's unrelated. I've run it locally to confirm the Process tests are passing on x64
{2AB65DDF-C9E1-46A6-A21F-03F9CB29A706}

@adamsitnik
adamsitnik merged commit b54e86d into mainApr 22, 2026
82 of 97 checks passed
@adamsitnik
adamsitnik deleted the copilot/implement-process-run-apis branch April 22, 2026 10:44
@github-actionsgithub-actionsBot locked and limited conversation to collaborators May 24, 2026
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants

@danmoseley@adamsitnik@jkotas
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Implement Process.Run, RunAsync, RunAndCaptureText, RunAndCaptureTextAsync APIs - #127210

Merged
adamsitnik merged 32 commits into
mainfrom
copilot/implement-process-run-apis
Apr 22, 2026
Merged

Implement Process.Run, RunAsync, RunAndCaptureText, RunAndCaptureTextAsync APIs#127210
adamsitnik merged 32 commits into
mainfrom
copilot/implement-process-run-apis

Conversation

CopilotAI commented Apr 21, 2026

Copy link
Copy Markdown
Contributor
  • Rebase onto main after base branch copilot/implement-issue-126293 was merged into main as PR Implement SafeProcessHandle.WaitForExit* methods #127022
  • Implement Process.Run, RunAsync, RunAndCaptureText, RunAndCaptureTextAsync APIs
  • RunAndCapture* PSI overloads require RedirectStandardOutput/Error to be enabled (no PSI mutation)
  • String overloads use CreateStartInfoForCapture helper that sets redirect flags
  • RunAsync/RunAndCaptureTextAsync always use WaitForExitOrKillOnCancellationAsync (CanBeCanceled check is already inside that method)
  • Comprehensive test coverage for all API parameters and permutations using [Theory]
  • Tests cover: Run (PSI, PSI+timeout, fileName, fileName+timeout/cancel), RunAndCaptureText (PSI, PSI+timeout, fileName, fileName+timeout/cancel), argument validation, UseShellExecute rejection, NotRedirected rejection
  • All 40 RunTests and 10 StartAndForgetTests pass

CopilotAIand others added 21 commits April 16, 2026 09:51
- Add WaitForExit, TryWaitForExit, WaitForExitOrKillOnTimeout,
WaitForExitAsync, WaitForExitOrKillOnCancellationAsync to
SafeProcessHandle
- Windows: uses ProcessWaitHandle + GetExitCodeProcess
- Unix: integrates with ProcessWaitState for reaping coordination
- Native: WaitPidExitedNoHang now returns terminating signal info
- ProcessWaitState: tracks terminating signal for ProcessExitStatus
- Ref assembly: updated with new API surface
- Tests: added comprehensive WaitForExit* tests
Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/3540beba-26c4-4014-b276-d6fa244eda82
Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>
…e ToTimeoutMilliseconds to ProcessUtils, remove KillCore, fix platform attributes, update native PAL
- ProcessWaitState: store ProcessExitStatus? instead of separate _exitCode/_terminatingSignal
- Native PAL: use TryConvertSignalCodeToPosixSignal for proper PosixSignal mapping
- Move ToTimeoutMilliseconds to ProcessUtils.cs, reuse from Process and SafeProcessHandle
- Remove separate KillCore methods on both platforms; use SignalCore on Unix, TerminateProcessCore on Windows
- Remove platform attributes from WaitForExit, TryWaitForExit, WaitForExitAsync (non-killing methods)
- Fix CreateExitStatus canceled logic: canceled && signal is not null
- Update Process.Unix.cs to consume ProcessExitStatus? from GetExited
Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/1a601c8b-3c5f-4596-9b8f-5e11188e35ae
Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>
… pragma, simplify Unix async via ProcessWaitState.WaitForExitAsync, add PlatformNotSupportedException checks, rename wasKilled to signalWasSent, add Debug.Assert, update ProcessHandlesTests.Windows.cs
Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/603f063f-b34a-42f8-ab6b-e1aa2df62675
Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>
- there is no need to start suspended process anymore, as we can wait on the handle to exit directly
- revert changes I did not like
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
…tests
- Fix GetWaitState() on Unix to lazily initialize _waitState from ProcessWaitState table
so that SafeProcessHandle from Process.SafeHandle works for WaitForExit*
- Add _lazyWaitStateHolder field to properly manage ref count lifecycle
- Convert signal test from Fact to Theory with SIGKILL and SIGTERM
- Add Process.SafeHandle WaitForExit* tests to ProcessWaitingTests
Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/52916352-c074-4483-8dca-72cf3696462e
Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>
…, rename test methods
Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/52916352-c074-4483-8dca-72cf3696462e
Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>
- Use WaitInMS timeout at line 55 per reviewer suggestion
- Merge two WaitForExit_ProcessExitsNormally tests into one
- Merge sync/async WaitForExit into theory with bool useAsync
- Merge sync/async WaitForExitOrKill normal-exit into theory
- Merge sync/async WaitForExitOrKill timeout/cancel into theory
Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/3a1553e0-3850-4588-b95f-5452296a0275
Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>
…ocessId) matching Process pattern
Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/3f4f9d58-e237-49c2-9220-e41731a20fde
Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>
…e lazy init
All SafeProcessHandle instances are now created with a ProcessWaitState:
- Added Holder(Holder) copy constructor to ProcessWaitState.Holder
- Added IncrementRefCount() to ProcessWaitState for ref counting
- SafeProcessHandle now owns its own Holder copy (disposed in ReleaseHandle)
- Made _waitState readonly, removed _lazyWaitStateHolder and EnsureWaitStateInitialized
- Updated GetProcessHandle() in Process.Unix.cs to pass Holder when creating SafeProcessHandle
Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/a866727c-2478-4cdc-a3ec-6ce0e20f929e
Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
…-child process on Unix
Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/fb9ffb85-16b8-436b-b588-0f5527b85606
Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>
…Async APIs
Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/6d89c552-8d80-40db-bf17-c2f9effc55ca
Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>

@adamsitnikadamsitnik 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 threadsrc/libraries/System.Diagnostics.Process/tests/RunTests.cs Outdated
@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.

…elpers, fix timeout tracking, reuse MapToArgumentList
Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/840381dc-b4f5-46ce-a7ed-bdde61b0ca90
Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>

CopilotAI commented Apr 21, 2026

Copy link
Copy Markdown
ContributorAuthor

@copilot address my feedback

All feedback addressed in bbb0c70. All 30 RunTests and 10 StartAndForgetTests pass.

CopilotAIand others added 4 commits April 21, 2026 21:56
…lOnCancellationAsync
Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/73a14058-c419-4277-b5e2-885c9c6c8607
Co-authored-by: danmoseley <6385855+danmoseley@users.noreply.github.com>

CopilotAI commented Apr 21, 2026

Copy link
Copy Markdown
ContributorAuthor

@copilot please look at afeedback and address as appropriate. use one separate commit for each piece of feedback.

All feedback addressed in separate commits:

  • fc2f007 — require RedirectStandard* on PSI overloads instead of mutating
  • 391c3c4 — simplify async methods by always using WaitForExitOrKillOnCancellationAsync
  • f78f6dc — audit and improve test coverage
  • c15a6ef — fix CancellationTokenSource leaks in tests

All 40 RunTests and 10 StartAndForgetTests pass.

Base automatically changed from copilot/implement-issue-126293 to mainApril 22, 2026 03:31
CopilotAIand others added 2 commits April 22, 2026 04:13
…Async APIs
- Run/RunAsync: synchronously/asynchronously starts a process, waits for exit, returns ProcessExitStatus
- RunAndCaptureText/RunAndCaptureTextAsync: starts a process, captures stdout/stderr, returns ProcessTextOutput
- PSI overloads for RunAndCapture* require RedirectStandardOutput and RedirectStandardError to be enabled
- String overloads use CreateStartInfoForCapture helper to set redirect flags
- All async methods always use WaitForExitOrKillOnCancellationAsync
- Comprehensive tests for all API parameters and permutations
Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>
Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>
CopilotAI requested review from Copilot and removed request for CopilotApril 22, 2026 04:16
@adamsitnik
adamsitnik enabled auto-merge (squash) April 22, 2026 04:43
@adamsitnik

Copy link
Copy Markdown
Member

/ba-g the linux x64 timeouts are hunting all opened PRs, I believe it's unrelated. I've run it locally to confirm the Process tests are passing on x64
{2AB65DDF-C9E1-46A6-A21F-03F9CB29A706}

@adamsitnik
adamsitnik merged commit b54e86d into mainApr 22, 2026
82 of 97 checks passed
@adamsitnik
adamsitnik deleted the copilot/implement-process-run-apis branch April 22, 2026 10:44
@github-actionsgithub-actionsBot locked and limited conversation to collaborators May 24, 2026
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants

@danmoseley@adamsitnik@jkotas
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

Implement Process.Run, RunAsync, RunAndCaptureText, RunAndCaptureTextAsync APIs - #127210

Merged
adamsitnik merged 32 commits into
mainfrom
copilot/implement-process-run-apis
Apr 22, 2026
Merged

Implement Process.Run, RunAsync, RunAndCaptureText, RunAndCaptureTextAsync APIs#127210
adamsitnik merged 32 commits into
mainfrom
copilot/implement-process-run-apis

Conversation

CopilotAI commented Apr 21, 2026

Copy link
Copy Markdown
Contributor
  • Rebase onto main after base branch copilot/implement-issue-126293 was merged into main as PR Implement SafeProcessHandle.WaitForExit* methods #127022
  • Implement Process.Run, RunAsync, RunAndCaptureText, RunAndCaptureTextAsync APIs
  • RunAndCapture* PSI overloads require RedirectStandardOutput/Error to be enabled (no PSI mutation)
  • String overloads use CreateStartInfoForCapture helper that sets redirect flags
  • RunAsync/RunAndCaptureTextAsync always use WaitForExitOrKillOnCancellationAsync (CanBeCanceled check is already inside that method)
  • Comprehensive test coverage for all API parameters and permutations using [Theory]
  • Tests cover: Run (PSI, PSI+timeout, fileName, fileName+timeout/cancel), RunAndCaptureText (PSI, PSI+timeout, fileName, fileName+timeout/cancel), argument validation, UseShellExecute rejection, NotRedirected rejection
  • All 40 RunTests and 10 StartAndForgetTests pass

CopilotAIand others added 21 commits April 16, 2026 09:51
- Add WaitForExit, TryWaitForExit, WaitForExitOrKillOnTimeout,
WaitForExitAsync, WaitForExitOrKillOnCancellationAsync to
SafeProcessHandle
- Windows: uses ProcessWaitHandle + GetExitCodeProcess
- Unix: integrates with ProcessWaitState for reaping coordination
- Native: WaitPidExitedNoHang now returns terminating signal info
- ProcessWaitState: tracks terminating signal for ProcessExitStatus
- Ref assembly: updated with new API surface
- Tests: added comprehensive WaitForExit* tests
Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/3540beba-26c4-4014-b276-d6fa244eda82
Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>
…e ToTimeoutMilliseconds to ProcessUtils, remove KillCore, fix platform attributes, update native PAL
- ProcessWaitState: store ProcessExitStatus? instead of separate _exitCode/_terminatingSignal
- Native PAL: use TryConvertSignalCodeToPosixSignal for proper PosixSignal mapping
- Move ToTimeoutMilliseconds to ProcessUtils.cs, reuse from Process and SafeProcessHandle
- Remove separate KillCore methods on both platforms; use SignalCore on Unix, TerminateProcessCore on Windows
- Remove platform attributes from WaitForExit, TryWaitForExit, WaitForExitAsync (non-killing methods)
- Fix CreateExitStatus canceled logic: canceled && signal is not null
- Update Process.Unix.cs to consume ProcessExitStatus? from GetExited
Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/1a601c8b-3c5f-4596-9b8f-5e11188e35ae
Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>
… pragma, simplify Unix async via ProcessWaitState.WaitForExitAsync, add PlatformNotSupportedException checks, rename wasKilled to signalWasSent, add Debug.Assert, update ProcessHandlesTests.Windows.cs
Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/603f063f-b34a-42f8-ab6b-e1aa2df62675
Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>
- there is no need to start suspended process anymore, as we can wait on the handle to exit directly
- revert changes I did not like
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
…tests
- Fix GetWaitState() on Unix to lazily initialize _waitState from ProcessWaitState table
so that SafeProcessHandle from Process.SafeHandle works for WaitForExit*
- Add _lazyWaitStateHolder field to properly manage ref count lifecycle
- Convert signal test from Fact to Theory with SIGKILL and SIGTERM
- Add Process.SafeHandle WaitForExit* tests to ProcessWaitingTests
Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/52916352-c074-4483-8dca-72cf3696462e
Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>
…, rename test methods
Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/52916352-c074-4483-8dca-72cf3696462e
Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>
- Use WaitInMS timeout at line 55 per reviewer suggestion
- Merge two WaitForExit_ProcessExitsNormally tests into one
- Merge sync/async WaitForExit into theory with bool useAsync
- Merge sync/async WaitForExitOrKill normal-exit into theory
- Merge sync/async WaitForExitOrKill timeout/cancel into theory
Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/3a1553e0-3850-4588-b95f-5452296a0275
Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>
…ocessId) matching Process pattern
Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/3f4f9d58-e237-49c2-9220-e41731a20fde
Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>
…e lazy init
All SafeProcessHandle instances are now created with a ProcessWaitState:
- Added Holder(Holder) copy constructor to ProcessWaitState.Holder
- Added IncrementRefCount() to ProcessWaitState for ref counting
- SafeProcessHandle now owns its own Holder copy (disposed in ReleaseHandle)
- Made _waitState readonly, removed _lazyWaitStateHolder and EnsureWaitStateInitialized
- Updated GetProcessHandle() in Process.Unix.cs to pass Holder when creating SafeProcessHandle
Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/a866727c-2478-4cdc-a3ec-6ce0e20f929e
Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
…-child process on Unix
Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/fb9ffb85-16b8-436b-b588-0f5527b85606
Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>
…Async APIs
Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/6d89c552-8d80-40db-bf17-c2f9effc55ca
Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>

@adamsitnikadamsitnik 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 threadsrc/libraries/System.Diagnostics.Process/tests/RunTests.cs Outdated
@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.

…elpers, fix timeout tracking, reuse MapToArgumentList
Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/840381dc-b4f5-46ce-a7ed-bdde61b0ca90
Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>

CopilotAI commented Apr 21, 2026

Copy link
Copy Markdown
ContributorAuthor

@copilot address my feedback

All feedback addressed in bbb0c70. All 30 RunTests and 10 StartAndForgetTests pass.

CopilotAIand others added 4 commits April 21, 2026 21:56
…lOnCancellationAsync
Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/73a14058-c419-4277-b5e2-885c9c6c8607
Co-authored-by: danmoseley <6385855+danmoseley@users.noreply.github.com>

CopilotAI commented Apr 21, 2026

Copy link
Copy Markdown
ContributorAuthor

@copilot please look at afeedback and address as appropriate. use one separate commit for each piece of feedback.

All feedback addressed in separate commits:

  • fc2f007 — require RedirectStandard* on PSI overloads instead of mutating
  • 391c3c4 — simplify async methods by always using WaitForExitOrKillOnCancellationAsync
  • f78f6dc — audit and improve test coverage
  • c15a6ef — fix CancellationTokenSource leaks in tests

All 40 RunTests and 10 StartAndForgetTests pass.

Base automatically changed from copilot/implement-issue-126293 to mainApril 22, 2026 03:31
CopilotAIand others added 2 commits April 22, 2026 04:13
…Async APIs
- Run/RunAsync: synchronously/asynchronously starts a process, waits for exit, returns ProcessExitStatus
- RunAndCaptureText/RunAndCaptureTextAsync: starts a process, captures stdout/stderr, returns ProcessTextOutput
- PSI overloads for RunAndCapture* require RedirectStandardOutput and RedirectStandardError to be enabled
- String overloads use CreateStartInfoForCapture helper to set redirect flags
- All async methods always use WaitForExitOrKillOnCancellationAsync
- Comprehensive tests for all API parameters and permutations
Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>
Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>
CopilotAI requested review from Copilot and removed request for CopilotApril 22, 2026 04:16
@adamsitnik
adamsitnik enabled auto-merge (squash) April 22, 2026 04:43
@adamsitnik

Copy link
Copy Markdown
Member

/ba-g the linux x64 timeouts are hunting all opened PRs, I believe it's unrelated. I've run it locally to confirm the Process tests are passing on x64
{2AB65DDF-C9E1-46A6-A21F-03F9CB29A706}

@adamsitnik
adamsitnik merged commit b54e86d into mainApr 22, 2026
82 of 97 checks passed
@adamsitnik
adamsitnik deleted the copilot/implement-process-run-apis branch April 22, 2026 10:44
@github-actionsgithub-actionsBot locked and limited conversation to collaborators May 24, 2026
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants

@danmoseley@adamsitnik@jkotas
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Implement Process.Run, RunAsync, RunAndCaptureText, RunAndCaptureTextAsync APIs - #127210

Merged
adamsitnik merged 32 commits into
mainfrom
copilot/implement-process-run-apis
Apr 22, 2026
Merged

Implement Process.Run, RunAsync, RunAndCaptureText, RunAndCaptureTextAsync APIs#127210
adamsitnik merged 32 commits into
mainfrom
copilot/implement-process-run-apis

Conversation

CopilotAI commented Apr 21, 2026

Copy link
Copy Markdown
Contributor
  • Rebase onto main after base branch copilot/implement-issue-126293 was merged into main as PR Implement SafeProcessHandle.WaitForExit* methods #127022
  • Implement Process.Run, RunAsync, RunAndCaptureText, RunAndCaptureTextAsync APIs
  • RunAndCapture* PSI overloads require RedirectStandardOutput/Error to be enabled (no PSI mutation)
  • String overloads use CreateStartInfoForCapture helper that sets redirect flags
  • RunAsync/RunAndCaptureTextAsync always use WaitForExitOrKillOnCancellationAsync (CanBeCanceled check is already inside that method)
  • Comprehensive test coverage for all API parameters and permutations using [Theory]
  • Tests cover: Run (PSI, PSI+timeout, fileName, fileName+timeout/cancel), RunAndCaptureText (PSI, PSI+timeout, fileName, fileName+timeout/cancel), argument validation, UseShellExecute rejection, NotRedirected rejection
  • All 40 RunTests and 10 StartAndForgetTests pass

CopilotAIand others added 21 commits April 16, 2026 09:51
- Add WaitForExit, TryWaitForExit, WaitForExitOrKillOnTimeout,
WaitForExitAsync, WaitForExitOrKillOnCancellationAsync to
SafeProcessHandle
- Windows: uses ProcessWaitHandle + GetExitCodeProcess
- Unix: integrates with ProcessWaitState for reaping coordination
- Native: WaitPidExitedNoHang now returns terminating signal info
- ProcessWaitState: tracks terminating signal for ProcessExitStatus
- Ref assembly: updated with new API surface
- Tests: added comprehensive WaitForExit* tests
Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/3540beba-26c4-4014-b276-d6fa244eda82
Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>
…e ToTimeoutMilliseconds to ProcessUtils, remove KillCore, fix platform attributes, update native PAL
- ProcessWaitState: store ProcessExitStatus? instead of separate _exitCode/_terminatingSignal
- Native PAL: use TryConvertSignalCodeToPosixSignal for proper PosixSignal mapping
- Move ToTimeoutMilliseconds to ProcessUtils.cs, reuse from Process and SafeProcessHandle
- Remove separate KillCore methods on both platforms; use SignalCore on Unix, TerminateProcessCore on Windows
- Remove platform attributes from WaitForExit, TryWaitForExit, WaitForExitAsync (non-killing methods)
- Fix CreateExitStatus canceled logic: canceled && signal is not null
- Update Process.Unix.cs to consume ProcessExitStatus? from GetExited
Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/1a601c8b-3c5f-4596-9b8f-5e11188e35ae
Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>
… pragma, simplify Unix async via ProcessWaitState.WaitForExitAsync, add PlatformNotSupportedException checks, rename wasKilled to signalWasSent, add Debug.Assert, update ProcessHandlesTests.Windows.cs
Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/603f063f-b34a-42f8-ab6b-e1aa2df62675
Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>
- there is no need to start suspended process anymore, as we can wait on the handle to exit directly
- revert changes I did not like
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
…tests
- Fix GetWaitState() on Unix to lazily initialize _waitState from ProcessWaitState table
so that SafeProcessHandle from Process.SafeHandle works for WaitForExit*
- Add _lazyWaitStateHolder field to properly manage ref count lifecycle
- Convert signal test from Fact to Theory with SIGKILL and SIGTERM
- Add Process.SafeHandle WaitForExit* tests to ProcessWaitingTests
Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/52916352-c074-4483-8dca-72cf3696462e
Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>
…, rename test methods
Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/52916352-c074-4483-8dca-72cf3696462e
Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>
- Use WaitInMS timeout at line 55 per reviewer suggestion
- Merge two WaitForExit_ProcessExitsNormally tests into one
- Merge sync/async WaitForExit into theory with bool useAsync
- Merge sync/async WaitForExitOrKill normal-exit into theory
- Merge sync/async WaitForExitOrKill timeout/cancel into theory
Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/3a1553e0-3850-4588-b95f-5452296a0275
Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>
…ocessId) matching Process pattern
Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/3f4f9d58-e237-49c2-9220-e41731a20fde
Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>
…e lazy init
All SafeProcessHandle instances are now created with a ProcessWaitState:
- Added Holder(Holder) copy constructor to ProcessWaitState.Holder
- Added IncrementRefCount() to ProcessWaitState for ref counting
- SafeProcessHandle now owns its own Holder copy (disposed in ReleaseHandle)
- Made _waitState readonly, removed _lazyWaitStateHolder and EnsureWaitStateInitialized
- Updated GetProcessHandle() in Process.Unix.cs to pass Holder when creating SafeProcessHandle
Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/a866727c-2478-4cdc-a3ec-6ce0e20f929e
Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
…-child process on Unix
Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/fb9ffb85-16b8-436b-b588-0f5527b85606
Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>
…Async APIs
Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/6d89c552-8d80-40db-bf17-c2f9effc55ca
Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>

@adamsitnikadamsitnik 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 threadsrc/libraries/System.Diagnostics.Process/tests/RunTests.cs Outdated
@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.

…elpers, fix timeout tracking, reuse MapToArgumentList
Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/840381dc-b4f5-46ce-a7ed-bdde61b0ca90
Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>

CopilotAI commented Apr 21, 2026

Copy link
Copy Markdown
ContributorAuthor

@copilot address my feedback

All feedback addressed in bbb0c70. All 30 RunTests and 10 StartAndForgetTests pass.

CopilotAIand others added 4 commits April 21, 2026 21:56
…lOnCancellationAsync
Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/73a14058-c419-4277-b5e2-885c9c6c8607
Co-authored-by: danmoseley <6385855+danmoseley@users.noreply.github.com>

CopilotAI commented Apr 21, 2026

Copy link
Copy Markdown
ContributorAuthor

@copilot please look at afeedback and address as appropriate. use one separate commit for each piece of feedback.

All feedback addressed in separate commits:

  • fc2f007 — require RedirectStandard* on PSI overloads instead of mutating
  • 391c3c4 — simplify async methods by always using WaitForExitOrKillOnCancellationAsync
  • f78f6dc — audit and improve test coverage
  • c15a6ef — fix CancellationTokenSource leaks in tests

All 40 RunTests and 10 StartAndForgetTests pass.

Base automatically changed from copilot/implement-issue-126293 to mainApril 22, 2026 03:31
CopilotAIand others added 2 commits April 22, 2026 04:13
…Async APIs
- Run/RunAsync: synchronously/asynchronously starts a process, waits for exit, returns ProcessExitStatus
- RunAndCaptureText/RunAndCaptureTextAsync: starts a process, captures stdout/stderr, returns ProcessTextOutput
- PSI overloads for RunAndCapture* require RedirectStandardOutput and RedirectStandardError to be enabled
- String overloads use CreateStartInfoForCapture helper to set redirect flags
- All async methods always use WaitForExitOrKillOnCancellationAsync
- Comprehensive tests for all API parameters and permutations
Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>
Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>
CopilotAI requested review from Copilot and removed request for CopilotApril 22, 2026 04:16
@adamsitnik
adamsitnik enabled auto-merge (squash) April 22, 2026 04:43
@adamsitnik

Copy link
Copy Markdown
Member

/ba-g the linux x64 timeouts are hunting all opened PRs, I believe it's unrelated. I've run it locally to confirm the Process tests are passing on x64
{2AB65DDF-C9E1-46A6-A21F-03F9CB29A706}

@adamsitnik
adamsitnik merged commit b54e86d into mainApr 22, 2026
82 of 97 checks passed
@adamsitnik
adamsitnik deleted the copilot/implement-process-run-apis branch April 22, 2026 10:44
@github-actionsgithub-actionsBot locked and limited conversation to collaborators May 24, 2026
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants

@danmoseley@adamsitnik@jkotas
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Implement Process.Run, RunAsync, RunAndCaptureText, RunAndCaptureTextAsync APIs - #127210

Merged
adamsitnik merged 32 commits into
mainfrom
copilot/implement-process-run-apis
Apr 22, 2026
Merged

Implement Process.Run, RunAsync, RunAndCaptureText, RunAndCaptureTextAsync APIs#127210
adamsitnik merged 32 commits into
mainfrom
copilot/implement-process-run-apis

Conversation

CopilotAI commented Apr 21, 2026

Copy link
Copy Markdown
Contributor
  • Rebase onto main after base branch copilot/implement-issue-126293 was merged into main as PR Implement SafeProcessHandle.WaitForExit* methods #127022
  • Implement Process.Run, RunAsync, RunAndCaptureText, RunAndCaptureTextAsync APIs
  • RunAndCapture* PSI overloads require RedirectStandardOutput/Error to be enabled (no PSI mutation)
  • String overloads use CreateStartInfoForCapture helper that sets redirect flags
  • RunAsync/RunAndCaptureTextAsync always use WaitForExitOrKillOnCancellationAsync (CanBeCanceled check is already inside that method)
  • Comprehensive test coverage for all API parameters and permutations using [Theory]
  • Tests cover: Run (PSI, PSI+timeout, fileName, fileName+timeout/cancel), RunAndCaptureText (PSI, PSI+timeout, fileName, fileName+timeout/cancel), argument validation, UseShellExecute rejection, NotRedirected rejection
  • All 40 RunTests and 10 StartAndForgetTests pass

CopilotAIand others added 21 commits April 16, 2026 09:51
- Add WaitForExit, TryWaitForExit, WaitForExitOrKillOnTimeout,
WaitForExitAsync, WaitForExitOrKillOnCancellationAsync to
SafeProcessHandle
- Windows: uses ProcessWaitHandle + GetExitCodeProcess
- Unix: integrates with ProcessWaitState for reaping coordination
- Native: WaitPidExitedNoHang now returns terminating signal info
- ProcessWaitState: tracks terminating signal for ProcessExitStatus
- Ref assembly: updated with new API surface
- Tests: added comprehensive WaitForExit* tests
Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/3540beba-26c4-4014-b276-d6fa244eda82
Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>
…e ToTimeoutMilliseconds to ProcessUtils, remove KillCore, fix platform attributes, update native PAL
- ProcessWaitState: store ProcessExitStatus? instead of separate _exitCode/_terminatingSignal
- Native PAL: use TryConvertSignalCodeToPosixSignal for proper PosixSignal mapping
- Move ToTimeoutMilliseconds to ProcessUtils.cs, reuse from Process and SafeProcessHandle
- Remove separate KillCore methods on both platforms; use SignalCore on Unix, TerminateProcessCore on Windows
- Remove platform attributes from WaitForExit, TryWaitForExit, WaitForExitAsync (non-killing methods)
- Fix CreateExitStatus canceled logic: canceled && signal is not null
- Update Process.Unix.cs to consume ProcessExitStatus? from GetExited
Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/1a601c8b-3c5f-4596-9b8f-5e11188e35ae
Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>
… pragma, simplify Unix async via ProcessWaitState.WaitForExitAsync, add PlatformNotSupportedException checks, rename wasKilled to signalWasSent, add Debug.Assert, update ProcessHandlesTests.Windows.cs
Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/603f063f-b34a-42f8-ab6b-e1aa2df62675
Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>
- there is no need to start suspended process anymore, as we can wait on the handle to exit directly
- revert changes I did not like
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
…tests
- Fix GetWaitState() on Unix to lazily initialize _waitState from ProcessWaitState table
so that SafeProcessHandle from Process.SafeHandle works for WaitForExit*
- Add _lazyWaitStateHolder field to properly manage ref count lifecycle
- Convert signal test from Fact to Theory with SIGKILL and SIGTERM
- Add Process.SafeHandle WaitForExit* tests to ProcessWaitingTests
Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/52916352-c074-4483-8dca-72cf3696462e
Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>
…, rename test methods
Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/52916352-c074-4483-8dca-72cf3696462e
Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>
- Use WaitInMS timeout at line 55 per reviewer suggestion
- Merge two WaitForExit_ProcessExitsNormally tests into one
- Merge sync/async WaitForExit into theory with bool useAsync
- Merge sync/async WaitForExitOrKill normal-exit into theory
- Merge sync/async WaitForExitOrKill timeout/cancel into theory
Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/3a1553e0-3850-4588-b95f-5452296a0275
Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>
…ocessId) matching Process pattern
Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/3f4f9d58-e237-49c2-9220-e41731a20fde
Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>
…e lazy init
All SafeProcessHandle instances are now created with a ProcessWaitState:
- Added Holder(Holder) copy constructor to ProcessWaitState.Holder
- Added IncrementRefCount() to ProcessWaitState for ref counting
- SafeProcessHandle now owns its own Holder copy (disposed in ReleaseHandle)
- Made _waitState readonly, removed _lazyWaitStateHolder and EnsureWaitStateInitialized
- Updated GetProcessHandle() in Process.Unix.cs to pass Holder when creating SafeProcessHandle
Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/a866727c-2478-4cdc-a3ec-6ce0e20f929e
Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
…-child process on Unix
Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/fb9ffb85-16b8-436b-b588-0f5527b85606
Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>
…Async APIs
Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/6d89c552-8d80-40db-bf17-c2f9effc55ca
Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>

@adamsitnikadamsitnik 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 threadsrc/libraries/System.Diagnostics.Process/tests/RunTests.cs Outdated
@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.

…elpers, fix timeout tracking, reuse MapToArgumentList
Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/840381dc-b4f5-46ce-a7ed-bdde61b0ca90
Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>

CopilotAI commented Apr 21, 2026

Copy link
Copy Markdown
ContributorAuthor

@copilot address my feedback

All feedback addressed in bbb0c70. All 30 RunTests and 10 StartAndForgetTests pass.

CopilotAIand others added 4 commits April 21, 2026 21:56
…lOnCancellationAsync
Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/73a14058-c419-4277-b5e2-885c9c6c8607
Co-authored-by: danmoseley <6385855+danmoseley@users.noreply.github.com>

CopilotAI commented Apr 21, 2026

Copy link
Copy Markdown
ContributorAuthor

@copilot please look at afeedback and address as appropriate. use one separate commit for each piece of feedback.

All feedback addressed in separate commits:

  • fc2f007 — require RedirectStandard* on PSI overloads instead of mutating
  • 391c3c4 — simplify async methods by always using WaitForExitOrKillOnCancellationAsync
  • f78f6dc — audit and improve test coverage
  • c15a6ef — fix CancellationTokenSource leaks in tests

All 40 RunTests and 10 StartAndForgetTests pass.

Base automatically changed from copilot/implement-issue-126293 to mainApril 22, 2026 03:31
CopilotAIand others added 2 commits April 22, 2026 04:13
…Async APIs
- Run/RunAsync: synchronously/asynchronously starts a process, waits for exit, returns ProcessExitStatus
- RunAndCaptureText/RunAndCaptureTextAsync: starts a process, captures stdout/stderr, returns ProcessTextOutput
- PSI overloads for RunAndCapture* require RedirectStandardOutput and RedirectStandardError to be enabled
- String overloads use CreateStartInfoForCapture helper to set redirect flags
- All async methods always use WaitForExitOrKillOnCancellationAsync
- Comprehensive tests for all API parameters and permutations
Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>
Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>
CopilotAI requested review from Copilot and removed request for CopilotApril 22, 2026 04:16
@adamsitnik
adamsitnik enabled auto-merge (squash) April 22, 2026 04:43
@adamsitnik

Copy link
Copy Markdown
Member

/ba-g the linux x64 timeouts are hunting all opened PRs, I believe it's unrelated. I've run it locally to confirm the Process tests are passing on x64
{2AB65DDF-C9E1-46A6-A21F-03F9CB29A706}

@adamsitnik
adamsitnik merged commit b54e86d into mainApr 22, 2026
82 of 97 checks passed
@adamsitnik
adamsitnik deleted the copilot/implement-process-run-apis branch April 22, 2026 10:44
@github-actionsgithub-actionsBot locked and limited conversation to collaborators May 24, 2026
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants

@danmoseley@adamsitnik@jkotas
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

Implement Process.Run, RunAsync, RunAndCaptureText, RunAndCaptureTextAsync APIs - #127210

Merged
adamsitnik merged 32 commits into
mainfrom
copilot/implement-process-run-apis
Apr 22, 2026
Merged

Implement Process.Run, RunAsync, RunAndCaptureText, RunAndCaptureTextAsync APIs#127210
adamsitnik merged 32 commits into
mainfrom
copilot/implement-process-run-apis

Conversation

CopilotAI commented Apr 21, 2026

Copy link
Copy Markdown
Contributor
  • Rebase onto main after base branch copilot/implement-issue-126293 was merged into main as PR Implement SafeProcessHandle.WaitForExit* methods #127022
  • Implement Process.Run, RunAsync, RunAndCaptureText, RunAndCaptureTextAsync APIs
  • RunAndCapture* PSI overloads require RedirectStandardOutput/Error to be enabled (no PSI mutation)
  • String overloads use CreateStartInfoForCapture helper that sets redirect flags
  • RunAsync/RunAndCaptureTextAsync always use WaitForExitOrKillOnCancellationAsync (CanBeCanceled check is already inside that method)
  • Comprehensive test coverage for all API parameters and permutations using [Theory]
  • Tests cover: Run (PSI, PSI+timeout, fileName, fileName+timeout/cancel), RunAndCaptureText (PSI, PSI+timeout, fileName, fileName+timeout/cancel), argument validation, UseShellExecute rejection, NotRedirected rejection
  • All 40 RunTests and 10 StartAndForgetTests pass

CopilotAIand others added 21 commits April 16, 2026 09:51
- Add WaitForExit, TryWaitForExit, WaitForExitOrKillOnTimeout,
WaitForExitAsync, WaitForExitOrKillOnCancellationAsync to
SafeProcessHandle
- Windows: uses ProcessWaitHandle + GetExitCodeProcess
- Unix: integrates with ProcessWaitState for reaping coordination
- Native: WaitPidExitedNoHang now returns terminating signal info
- ProcessWaitState: tracks terminating signal for ProcessExitStatus
- Ref assembly: updated with new API surface
- Tests: added comprehensive WaitForExit* tests
Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/3540beba-26c4-4014-b276-d6fa244eda82
Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>
…e ToTimeoutMilliseconds to ProcessUtils, remove KillCore, fix platform attributes, update native PAL
- ProcessWaitState: store ProcessExitStatus? instead of separate _exitCode/_terminatingSignal
- Native PAL: use TryConvertSignalCodeToPosixSignal for proper PosixSignal mapping
- Move ToTimeoutMilliseconds to ProcessUtils.cs, reuse from Process and SafeProcessHandle
- Remove separate KillCore methods on both platforms; use SignalCore on Unix, TerminateProcessCore on Windows
- Remove platform attributes from WaitForExit, TryWaitForExit, WaitForExitAsync (non-killing methods)
- Fix CreateExitStatus canceled logic: canceled && signal is not null
- Update Process.Unix.cs to consume ProcessExitStatus? from GetExited
Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/1a601c8b-3c5f-4596-9b8f-5e11188e35ae
Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>
… pragma, simplify Unix async via ProcessWaitState.WaitForExitAsync, add PlatformNotSupportedException checks, rename wasKilled to signalWasSent, add Debug.Assert, update ProcessHandlesTests.Windows.cs
Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/603f063f-b34a-42f8-ab6b-e1aa2df62675
Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>
- there is no need to start suspended process anymore, as we can wait on the handle to exit directly
- revert changes I did not like
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
…tests
- Fix GetWaitState() on Unix to lazily initialize _waitState from ProcessWaitState table
so that SafeProcessHandle from Process.SafeHandle works for WaitForExit*
- Add _lazyWaitStateHolder field to properly manage ref count lifecycle
- Convert signal test from Fact to Theory with SIGKILL and SIGTERM
- Add Process.SafeHandle WaitForExit* tests to ProcessWaitingTests
Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/52916352-c074-4483-8dca-72cf3696462e
Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>
…, rename test methods
Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/52916352-c074-4483-8dca-72cf3696462e
Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>
- Use WaitInMS timeout at line 55 per reviewer suggestion
- Merge two WaitForExit_ProcessExitsNormally tests into one
- Merge sync/async WaitForExit into theory with bool useAsync
- Merge sync/async WaitForExitOrKill normal-exit into theory
- Merge sync/async WaitForExitOrKill timeout/cancel into theory
Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/3a1553e0-3850-4588-b95f-5452296a0275
Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>
…ocessId) matching Process pattern
Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/3f4f9d58-e237-49c2-9220-e41731a20fde
Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>
…e lazy init
All SafeProcessHandle instances are now created with a ProcessWaitState:
- Added Holder(Holder) copy constructor to ProcessWaitState.Holder
- Added IncrementRefCount() to ProcessWaitState for ref counting
- SafeProcessHandle now owns its own Holder copy (disposed in ReleaseHandle)
- Made _waitState readonly, removed _lazyWaitStateHolder and EnsureWaitStateInitialized
- Updated GetProcessHandle() in Process.Unix.cs to pass Holder when creating SafeProcessHandle
Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/a866727c-2478-4cdc-a3ec-6ce0e20f929e
Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
…-child process on Unix
Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/fb9ffb85-16b8-436b-b588-0f5527b85606
Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>
…Async APIs
Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/6d89c552-8d80-40db-bf17-c2f9effc55ca
Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>

@adamsitnikadamsitnik 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 threadsrc/libraries/System.Diagnostics.Process/tests/RunTests.cs Outdated
@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.

…elpers, fix timeout tracking, reuse MapToArgumentList
Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/840381dc-b4f5-46ce-a7ed-bdde61b0ca90
Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>

CopilotAI commented Apr 21, 2026

Copy link
Copy Markdown
ContributorAuthor

@copilot address my feedback

All feedback addressed in bbb0c70. All 30 RunTests and 10 StartAndForgetTests pass.

CopilotAIand others added 4 commits April 21, 2026 21:56
…lOnCancellationAsync
Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/73a14058-c419-4277-b5e2-885c9c6c8607
Co-authored-by: danmoseley <6385855+danmoseley@users.noreply.github.com>

CopilotAI commented Apr 21, 2026

Copy link
Copy Markdown
ContributorAuthor

@copilot please look at afeedback and address as appropriate. use one separate commit for each piece of feedback.

All feedback addressed in separate commits:

  • fc2f007 — require RedirectStandard* on PSI overloads instead of mutating
  • 391c3c4 — simplify async methods by always using WaitForExitOrKillOnCancellationAsync
  • f78f6dc — audit and improve test coverage
  • c15a6ef — fix CancellationTokenSource leaks in tests

All 40 RunTests and 10 StartAndForgetTests pass.

Base automatically changed from copilot/implement-issue-126293 to mainApril 22, 2026 03:31
CopilotAIand others added 2 commits April 22, 2026 04:13
…Async APIs
- Run/RunAsync: synchronously/asynchronously starts a process, waits for exit, returns ProcessExitStatus
- RunAndCaptureText/RunAndCaptureTextAsync: starts a process, captures stdout/stderr, returns ProcessTextOutput
- PSI overloads for RunAndCapture* require RedirectStandardOutput and RedirectStandardError to be enabled
- String overloads use CreateStartInfoForCapture helper to set redirect flags
- All async methods always use WaitForExitOrKillOnCancellationAsync
- Comprehensive tests for all API parameters and permutations
Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>
Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>
CopilotAI requested review from Copilot and removed request for CopilotApril 22, 2026 04:16
@adamsitnik
adamsitnik enabled auto-merge (squash) April 22, 2026 04:43
@adamsitnik

Copy link
Copy Markdown
Member

/ba-g the linux x64 timeouts are hunting all opened PRs, I believe it's unrelated. I've run it locally to confirm the Process tests are passing on x64
{2AB65DDF-C9E1-46A6-A21F-03F9CB29A706}

@adamsitnik
adamsitnik merged commit b54e86d into mainApr 22, 2026
82 of 97 checks passed
@adamsitnik
adamsitnik deleted the copilot/implement-process-run-apis branch April 22, 2026 10:44
@github-actionsgithub-actionsBot locked and limited conversation to collaborators May 24, 2026
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants

@danmoseley@adamsitnik@jkotas