chore: Harden integration-test crash uploads in CI - #1496
Conversation
The desktop crash test can be flaky because both desktop backends can race the upload on shutdown: crashpad uploads out-of-process while the crashing process is already exiting, and the native out-of-process daemon drains its transport bounded by ShutdownTimeout (default 5000ms), which can be too short for a large envelope or slow link (the same root cause seen dropping crashes on the Xbox native backend). Non-crash tests upload via the SDK transport on sentry_close and hit the same limit. Raise ShutdownTimeout so the native daemon's crash upload and async event uploads have time to drain, and enable CrashpadWaitForUpload so the crashpad legs wait for the crash upload before exiting. Also include the sentry-native database (.sentry-native) in the on-failure artifacts for the Windows and Linux integration tests to simplify diagnosing missing/failed uploads.
8efa3b0 to
d6b9465
Compare
actions/upload-artifact skips hidden files by default, which dropped the dotted .sentry-native crash DB (daemon log, minidumps) from the failure artifacts.
Stack-overflow crash capture intermittently dies in-process (secondary 0xC0000005, no minidump produced) because the default 64 KiB guarantee is not always enough for UE's handler chain. SENTRY_HANDLER_STACK_SIZE is read by sentry-native at init, so no rebuild is needed.
Points the submodule at fix/thread-stack-guarantee-static-init (master + fix): kernel32 caching now precedes backend startup in static builds so the default thread stack guarantee is actually applied, and the native backend now sets it like the other backends do. This should let the in-process handlers survive stack-overflow crashes in the Windows integration tests.
Dispatched runs get their own concurrency group (run_id fallback), so multiple validation runs can execute in parallel without canceling the PR run.
The crash-capture test intermittently fails with "Expected 1 EVENT_CAPTURED line(s) but found 0": real SauceLabs devices emit thousands of unrelated log lines per second (AuthPII alone was ~8k of the ~10k captured lines), evicting UE's output from the captured log window before the harness reads it. Use app-runner's SAUCE_LOGCAT_FILTER (getsentry/app-runner#53, already in the pinned revision) to filter at capture time.
The server computes replay duration from segment timestamps, which shift with crash handling timing (observed 6 vs the sidecar's nominal 5 seconds), so an exact match is inherently flaky.
The stack guarantee fix branch was rebased for the upstream PR (getsentry/sentry-native#1918); the previously pinned commit no longer exists on any branch.
49baacf to
278fc97
Compare
The thread stack guarantee fix (getsentry/sentry-native#1918) will be picked up via a separate dependency update PR once it merges upstream.
Minidumps and envelopes contain process memory of the crashed test app (on Linux even the full environment block), which may hold CI secrets. Restrict the artifact to the daemon logs, which carry the diagnostic value.
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 1db445a. Configure here.
JoshuaMoelans
left a comment
There was a problem hiding this comment.
LGTM, just small q on the Replay Duration
| It "Should have expected replay duration" { | ||
| # The staged clip's sidecar claims a 5000 ms duration | ||
| $script:ReplayEvent.duration | Should -Be 5 | ||
| } | ||
|
|
There was a problem hiding this comment.
q: does it make sense to fully remove the assertion, or could we simply weaken it (e.g., > 3)? maybe not necessary since we already check for the segment count above though
There was a problem hiding this comment.
Given that we can't reliably determine replay duration here I'd say we drop this assertion entirely. Probably segment count check is sufficient for now.

The integration tests were flaky in CI for several distinct reasons - each confirmed from the failure artifacts this PR started capturing:
sentry_close, bounded byShutdownTimeout(default 5000 ms). Large envelopes or a slow link can exceed that window and the in-flight upload gets cancelled. The same drain-on-shutdown bound matters for the sentry-xbox extension, so we want generous headroom here regardless of the desktop legs. On the crashpad legs, the crashing process can also exit before the out-of-process handler finishes its upload unless it is configured to wait.sentry-crashdaemon captured the crash but sometimes failed to upload the envelope (WinHttpSendRequesterror 8,ERROR_NOT_ENOUGH_MEMORY); with no retry or durable fallback the event was lost.AuthPIIspam spanning 1.2 s), evicting UE'sEVENT_CAPTUREDmarker before the harness reads the log. The crash itself succeeded.Key Changes
sample/Config/DefaultEngine.iniShutdownTimeout=30000- gives the native daemon's crash upload and all async (non-crash) event uploads time to finish on shutdown before the transport is torn down. Drains early when the queue empties, so there is no slowdown when uploads are fast.CrashpadWaitForUpload=True- on the crashpad legs, the process waits for the crashpad upload to complete before exiting, so the crash is reliably delivered during the crash run.integration-test-windows.yml/integration-test-linux.ymlsample-build/SentryPlayground/.sentry-native/in the on-failure artifacts so the crash DB (minidumps, pending/completed uploads, daemon logs) is available when a test fails.integration-test-android.ymlSAUCE_LOGCAT_FILTER(via feat(sauce): Filter Android logcat by given tags app-runner#53, already in the pinned revision) captures onlyUE/Sentry/tombstone tags so app markers can't be evicted by device spam.SentryPlaygroundTestUtils.{h,cpp}, SentryCrashTest.cppSetMemoryLimit(HeadroomMB)util: the process self-assigns a Job Object withJOB_OBJECT_LIMIT_PROCESS_MEMORY= current commit + headroom (Windows-only, no-op elsewhere). The OOM test calls it with 4 GB, so allocation fails in-process while the runner (and the crash daemon) keep full memory headroom. Also drops the OOM test from ~6.5 min of pagefile thrashing to ~7 s.Integration.Desktop.Tests.ps1Notes
ShutdownTimeoutand the.sentry-nativeartifact help both the crashpad and native desktop legs;CrashpadWaitForUploadis a no-op on the native legs, so it is safe there..sentry-nativeartifact path assumesDatabaseLocation=ProjectUserDirectoryresolves to the packaged project dir (sibling ofSaved/Logs/).Related Items
#skip-changelog