[ci] Set __PWSH_LOGIN_CHECKED to avoid macOS pwsh 'procargs failed' startup crashes - #35724
Merged
Merged
Conversation
…tartup crashes
PowerShell 7.4.x intermittently aborts at startup on macOS with:
Call to 'procargs' failed with errno 5
Unhandled exception. Microsoft.PowerShell.ManagedPSEntry+StartupException
at Microsoft.PowerShell.ManagedPSEntry.ThrowOnFailure(String call, Int32 code)
at Microsoft.PowerShell.ManagedPSEntry.AttemptExecPwshLogin(String[] args)
at Microsoft.PowerShell.ManagedPSEntry.Main(String[] args)
This is PowerShell/PowerShell#20802, open and untriaged since Nov 2023.
AttemptExecPwshLogin uses sysctl(KERN_PROCARGS2) to detect login-shell
mode; that syscall races on macOS and intermittently returns errno 5,
aborting startup before pwsh reads any user script.
PowerShell itself ships a short-circuit env var __PWSH_LOGIN_CHECKED;
when set, AttemptExecPwshLogin returns immediately and never reaches
the racy syscall. Setting it pipeline-wide in common/variables.yml
(included by every macOS-touching pipeline) eliminates the flake with
zero behavior change in CI (we never want login-shell semantics there).
Hit on internal dnceng dotnet-maui build 2990586
(release/11.0.1xx-preview5).
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Contributor
|
🚀 Dogfood this PR with:
curl -fsSL https://raw.githubusercontent.com/dotnet/maui/main/eng/scripts/get-maui-pr.sh | bash -s -- 35724Or
iex "& { $(irm https://raw.githubusercontent.com/dotnet/maui/main/eng/scripts/get-maui-pr.ps1) } 35724" |
Redth
approved these changes
Jun 3, 2026
This was referenced Jun 3, 2026
This was referenced Jun 4, 2026
Dhivya-SF4094
pushed a commit
to Dhivya-SF4094/maui
that referenced
this pull request
Jun 15, 2026
…tartup crashes (dotnet#35724) <!-- Please let the below note in for people that find this PR --> > [!NOTE] > Are you waiting for the changes in this PR to be merged? > It would be very helpful if you could [test the resulting artifacts](https://github.com/dotnet/maui/wiki/Testing-PR-Builds) from this PR and let us know in a comment if this change resolves your issue. Thank you! ## Description PowerShell 7.4.x intermittently crashes at startup on macOS with: ``` Call to 'procargs' failed with errno 5 Unhandled exception. Microsoft.PowerShell.ManagedPSEntry+StartupException at Microsoft.PowerShell.ManagedPSEntry.ThrowOnFailure(String call, Int32 code) at Microsoft.PowerShell.ManagedPSEntry.AttemptExecPwshLogin(String[] args) at Microsoft.PowerShell.ManagedPSEntry.Main(String[] args) ``` This is [PowerShell/PowerShell#20802](PowerShell/PowerShell#20802) — open and untriaged since November 2023, **0 comments, no linked PRs, no fix shipped**. The crash happens in `AttemptExecPwshLogin`, which on macOS calls `sysctl(KERN_PROCARGS2)` to inspect its own `argv[0]` and decide whether pwsh was launched as a login shell. That `sysctl` call races intermittently and returns `errno 5`, aborting startup before pwsh reads any user script. ## Repro / impact Hit on the internal `dotnet-maui` pipeline (definition 1095), build **2990586**, during release-prep for `release/11.0.1xx-preview5`: > `##[section]Starting: Provision Android SDK - Common Packages` → `Call to 'procargs' failed with errno 5` → task fails with exit code `null`. A rerun on a different agent passed, but every macOS `pwsh:` / `PowerShell@2` step in the pipeline is a flake risk going forward. Inventory: ~57 pwsh tasks across 15 pipeline YAMLs, ~45 of them on macOS-eligible jobs. ## Fix PowerShell itself ships a short-circuit for this code path. From [`src/powershell/Program.cs`](https://github.com/PowerShell/PowerShell/blob/master/src/powershell/Program.cs): ```csharp private const string LOGIN_ENV_VAR_NAME = "__PWSH_LOGIN_CHECKED"; if (Environment.GetEnvironmentVariable(LOGIN_ENV_VAR_NAME) != null) { Environment.SetEnvironmentVariable(LOGIN_ENV_VAR_NAME, null); return; // ← skips the racy sysctl(KERN_PROCARGS2) entirely } ``` Setting `__PWSH_LOGIN_CHECKED=1` makes pwsh skip the racy syscall. This PR declares it as a pipeline-level variable in `eng/pipelines/common/variables.yml` (included by every macOS-touching pipeline — `ci.yml`, `ci-official.yml`, `ci-device-tests.yml`, `ci-copilot.yml`, `ci-uitests.yml`, `device-tests.yml`, `ui-tests.yml`, `handlers.yml`, etc.). Per [AzDO docs](https://learn.microsoft.com/azure/devops/pipelines/process/variables), user-defined variables are injected as environment variables for every task — so every `pwsh:` / `PowerShell@2` step in every job inherits it. ## Safety analysis This is safe because: - **CI never wants login-shell semantics.** No `-Login` flag, no leading `-` in `argv[0]`. The skipped code's `IsLogin()` check would have returned `false` and the function would have returned without doing anything visible. We just avoid the broken syscall that precedes that decision. - **The env var is single-use per process.** `AttemptExecPwshLogin` consumes it via `SetEnvironmentVariable(LOGIN_ENV_VAR_NAME, null)`, so nested `pwsh-launches-pwsh` scenarios still work normally (each new task gets a fresh AzDO-injected value). - **Windows is unaffected.** The read is inside a `#if UNIX` block; Windows pwsh ignores the var entirely. Setting it on Windows agents is a no-op. - **Safe even under `-Login`.** If a future step explicitly adds `-Login`, the short-circuit still routes around the broken syscall — the same syscall the login-shell *detection* relies on. So there's no regression even in that (currently nonexistent) use case. ## Empirical validation Verified locally on `pwsh 7.4.5` / macOS 26.5 (same 7.4.x minor as the CI agent that crashed): | Run | Command | Result | | --- | --- | --- | | Control | `pwsh ... -Command 'Write-Output "envvar=[$Env:__PWSH_LOGIN_CHECKED]"'` | `envvar=[]` (var unset; nothing to clear) | | Test | `__PWSH_LOGIN_CHECKED=1 pwsh ... -Command 'Write-Output "envvar=[$Env:__PWSH_LOGIN_CHECKED]"'` | `envvar=[]` ← **proves the short-circuit ran** (the only line that clears the var is inside the skip-path; if it cleared, the racy syscall was never reached) | | Soak | 100 × `__PWSH_LOGIN_CHECKED=1 pwsh ... -Command 'exit 0'` | **0/100 failures**; no behavioral change | ## Backport plan - This PR: `main` (.NET 10 SR dev). Drives the fix into ongoing servicing builds. - Will cherry-pick to `net11.0` afterward (where build 2990586 crashed during preview5 prep). Diff is verified to apply cleanly to both branches. ## Related macOS-agent flakes (out of scope) The same dnceng macOS agent pool has produced other, *unrelated* flakes during this release-prep window (e.g. `IDEDownloadableMetalToolchainCoordinator: Failed to remount` and `iOS 26.2 platform not installed` on builds 2990581 and 2990384). Those are agent-image issues and need agent-side fixes — they're not addressed here. This PR fixes one specific class of macOS flake (pwsh startup race), not all of them. Co-authored-by: bot <bot@test> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to subscribe to this conversation on GitHub.
Already have an account?
Sign in.
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Note
Are you waiting for the changes in this PR to be merged?
It would be very helpful if you could test the resulting artifacts from this PR and let us know in a comment if this change resolves your issue. Thank you!
Description
PowerShell 7.4.x intermittently crashes at startup on macOS with:
This is PowerShell/PowerShell#20802 — open and untriaged since November 2023, 0 comments, no linked PRs, no fix shipped. The crash happens in
AttemptExecPwshLogin, which on macOS callssysctl(KERN_PROCARGS2)to inspect its ownargv[0]and decide whether pwsh was launched as a login shell. Thatsysctlcall races intermittently and returnserrno 5, aborting startup before pwsh reads any user script.Repro / impact
Hit on the internal
dotnet-mauipipeline (definition 1095), build 2990586, during release-prep forrelease/11.0.1xx-preview5:A rerun on a different agent passed, but every macOS
pwsh:/PowerShell@2step in the pipeline is a flake risk going forward. Inventory: ~57 pwsh tasks across 15 pipeline YAMLs, ~45 of them on macOS-eligible jobs.Fix
PowerShell itself ships a short-circuit for this code path. From
src/powershell/Program.cs:Setting
__PWSH_LOGIN_CHECKED=1makes pwsh skip the racy syscall. This PR declares it as a pipeline-level variable ineng/pipelines/common/variables.yml(included by every macOS-touching pipeline —ci.yml,ci-official.yml,ci-device-tests.yml,ci-copilot.yml,ci-uitests.yml,device-tests.yml,ui-tests.yml,handlers.yml, etc.). Per AzDO docs, user-defined variables are injected as environment variables for every task — so everypwsh:/PowerShell@2step in every job inherits it.Safety analysis
This is safe because:
-Loginflag, no leading-inargv[0]. The skipped code'sIsLogin()check would have returnedfalseand the function would have returned without doing anything visible. We just avoid the broken syscall that precedes that decision.AttemptExecPwshLoginconsumes it viaSetEnvironmentVariable(LOGIN_ENV_VAR_NAME, null), so nestedpwsh-launches-pwshscenarios still work normally (each new task gets a fresh AzDO-injected value).#if UNIXblock; Windows pwsh ignores the var entirely. Setting it on Windows agents is a no-op.-Login. If a future step explicitly adds-Login, the short-circuit still routes around the broken syscall — the same syscall the login-shell detection relies on. So there's no regression even in that (currently nonexistent) use case.Empirical validation
Verified locally on
pwsh 7.4.5/ macOS 26.5 (same 7.4.x minor as the CI agent that crashed):pwsh ... -Command 'Write-Output "envvar=[$Env:__PWSH_LOGIN_CHECKED]"'envvar=[](var unset; nothing to clear)__PWSH_LOGIN_CHECKED=1 pwsh ... -Command 'Write-Output "envvar=[$Env:__PWSH_LOGIN_CHECKED]"'envvar=[]← proves the short-circuit ran (the only line that clears the var is inside the skip-path; if it cleared, the racy syscall was never reached)__PWSH_LOGIN_CHECKED=1 pwsh ... -Command 'exit 0'Backport plan
main(.NET 10 SR dev). Drives the fix into ongoing servicing builds.net11.0afterward (where build 2990586 crashed during preview5 prep). Diff is verified to apply cleanly to both branches.Related macOS-agent flakes (out of scope)
The same dnceng macOS agent pool has produced other, unrelated flakes during this release-prep window (e.g.
IDEDownloadableMetalToolchainCoordinator: Failed to remountandiOS 26.2 platform not installedon builds 2990581 and 2990384). Those are agent-image issues and need agent-side fixes — they're not addressed here. This PR fixes one specific class of macOS flake (pwsh startup race), not all of them.