Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
73 changes: 73 additions & 0 deletions .github/workflows/ci-stress.yml
Original file line number Diff line number Diff line change
Expand Up @@ -141,12 +141,32 @@ jobs:
- name: Build (once)
run: dotnet build tests/Reactor.SelfTests/Reactor.SelfTests.csproj --no-restore --configuration Debug -p:Platform=x64

- name: Configure crash dump capture
shell: pwsh
run: |
$dir = "${{ runner.temp }}\crashdumps"
New-Item -ItemType Directory -Force -Path $dir | Out-Null
# WER LocalDumps catches native fail-fasts / AVs (e.g. the 0xC0000409
# STATUS_STACK_BUFFER_OVERRUN crash) that bypass the CLR's createdump
# handler. Global key => applies to the spawned Reactor.AppTests.Host.exe.
$wer = 'HKLM:\SOFTWARE\Microsoft\Windows\Windows Error Reporting\LocalDumps'
New-Item -Path $wer -Force | Out-Null
New-ItemProperty -Path $wer -Name DumpFolder -Value $dir -PropertyType ExpandString -Force | Out-Null
New-ItemProperty -Path $wer -Name DumpType -Value 2 -PropertyType DWord -Force | Out-Null
New-ItemProperty -Path $wer -Name DumpCount -Value 10 -PropertyType DWord -Force | Out-Null
Write-Host "Crash dumps -> $dir (WER full + CLR createdump heap)"

- name: Stress loop
shell: pwsh
env:
PER_SHARD: ${{ needs.plan.outputs.per-shard }}
REMAINDER: ${{ needs.plan.outputs.remainder }}
SHARD_INDEX: ${{ matrix.shard }}
# CLR createdump for the spawned host subprocess (env is inherited).
DOTNET_DbgEnableMiniDump: "1"
COMPlus_DbgEnableMiniDump: "1"
DOTNET_DbgMiniDumpType: "2"
DOTNET_DbgMiniDumpName: ${{ runner.temp }}\crashdumps\coreclr.%p.dmp
run: |
$per = [int]$env:PER_SHARD
$rem = [int]$env:REMAINDER
Expand All @@ -170,6 +190,35 @@ jobs:
}
Write-Host "Shard ${idx}: $count iterations passed."

- name: Analyze crash dumps (SOS)
if: ${{ failure() }}
shell: pwsh
run: |
$dir = "${{ runner.temp }}\crashdumps"
$dumps = Get-ChildItem $dir -Filter *.dmp -ErrorAction SilentlyContinue
if (-not $dumps) { Write-Host "No dumps to analyze."; exit 0 }
dotnet tool install --global dotnet-dump 2>&1 | Out-Host
$tool = Join-Path $env:USERPROFILE ".dotnet\tools\dotnet-dump.exe"
foreach ($d in $dumps) {
$txt = "$($d.FullName).sos.txt"
Write-Host "::group::SOS analyze $($d.Name)"
& $tool analyze $d.FullName `
-c "clrthreads" `
-c "clrstack -all" `
-c "pe -nested" `
-c "dumpheap -stat -type Exception" `
-c "exit" 2>&1 | Tee-Object -FilePath $txt | Out-Host
Write-Host "::endgroup::"
}

- name: Upload crash dumps
if: ${{ failure() }}
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: selftest-crashdumps-shard-${{ matrix.shard }}
path: ${{ runner.temp }}/crashdumps/*
if-no-files-found: ignore

integration-tests:
name: Integration (shard ${{ matrix.shard }})
needs: plan
Expand Down Expand Up @@ -252,13 +301,29 @@ jobs:
-o ${{ runner.temp }}/aot-publish
--nologo

- name: Configure crash dump capture
shell: pwsh
run: |
$dir = "${{ runner.temp }}\crashdumps"
New-Item -ItemType Directory -Force -Path $dir | Out-Null
$wer = 'HKLM:\SOFTWARE\Microsoft\Windows\Windows Error Reporting\LocalDumps'
New-Item -Path $wer -Force | Out-Null
New-ItemProperty -Path $wer -Name DumpFolder -Value $dir -PropertyType ExpandString -Force | Out-Null
New-ItemProperty -Path $wer -Name DumpType -Value 2 -PropertyType DWord -Force | Out-Null
New-ItemProperty -Path $wer -Name DumpCount -Value 10 -PropertyType DWord -Force | Out-Null
Write-Host "Crash dumps -> $dir (WER full + CLR createdump heap)"

- name: Stress loop
shell: pwsh
env:
PER_SHARD: ${{ needs.plan.outputs.per-shard }}
REMAINDER: ${{ needs.plan.outputs.remainder }}
SHARD_INDEX: ${{ matrix.shard }}
FILTER: ${{ inputs.filter }}
DOTNET_DbgEnableMiniDump: "1"
COMPlus_DbgEnableMiniDump: "1"
DOTNET_DbgMiniDumpType: "2"
DOTNET_DbgMiniDumpName: ${{ runner.temp }}\crashdumps\coreclr.%p.dmp
run: |
$exe = Join-Path '${{ runner.temp }}/aot-publish' 'Reactor.AppTests.Host.exe'
if (-not (Test-Path $exe)) { Write-Host "::error::AOT host not found at $exe"; exit 1 }
Expand Down Expand Up @@ -296,6 +361,14 @@ jobs:
path: aot-*.tap
if-no-files-found: ignore

- name: Upload crash dumps
if: ${{ failure() }}
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: aot-crashdumps-shard-${{ matrix.shard }}
path: ${{ runner.temp }}/crashdumps/*
if-no-files-found: ignore

summary:
name: Stress summary
needs: [plan, unit-tests, selftests, aot-selftests, integration-tests]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,14 @@ private static void ApplySwipeItems(WinUI.SwipeControl control, SwipeControlElem
{
if (data is not { Length: > 0 }) return null;
var items = new WinUI.SwipeItems { Mode = mode };
foreach (var entry in data) items.Add(CreateSwipeItem(entry));
// WinUI constraint: an Execute-mode SwipeItems may contain only ONE item.
// Adding a second throws ArgumentException ("Execute items should only have
// one item") from native WinUI; that exception escapes the imperative
// reconciler into the XAML dispatcher and the framework fail-fasts the
// whole process with a stowed exception (0xC000027B / exit 0xC0000409).
// Honor the constraint here so invalid authoring can never crash the host.
var count = mode == WinUI.SwipeMode.Execute ? 1 : data.Length;
for (var i = 0; i < count; i++) items.Add(CreateSwipeItem(data[i]));
return items;
}

Expand Down
Loading