Skip to content

Collect all crash dumps in dump directory (#4186)#8268

Open
Evangelink wants to merge 5 commits into
mainfrom
dev/evangelink/issue-4186-crashdump-collect-all-dumps
Open

Collect all crash dumps in dump directory (#4186)#8268
Evangelink wants to merge 5 commits into
mainfrom
dev/evangelink/issue-4186-crashdump-collect-all-dumps

Conversation

@Evangelink
Copy link
Copy Markdown
Member

Fixes #4186.

Problem

When the testhost crashes alongside one or more child processes, the .NET runtime writes a separate dump for each crashing process using the configured dump file name pattern (e.g. MyApp_%p_crash.dmp, where %p expands to the PID). Previously the crash-dump extension only reported the testhost's own dump (matched by PID), so dumps produced by child processes that crashed at the same time were silently dropped.

Fix

In CrashDumpProcessLifetimeHandler.OnTestHostProcessExitedAsync:

  • Convert the dump file name pattern into a wildcard search pattern by replacing every %X placeholder (%p, %e, %h, %t, …) with * (collapsing adjacent wildcards).
  • Enumerate every file in the dump directory matching that pattern and publish each as a FileArtifact. This collects both the testhost dump and any child-process dumps written during the same crash.
  • The existing *.dmp fallback (when nothing matches the pattern) is kept; the fallback path is also normalized to use CrashDumpArtifactDisplayName instead of the extension's own CrashDumpDisplayName for the artifact display name.

Tests

Added a parameterized unit test in CrashDumpTests.cs (ReplaceCrashDumpPlaceholdersWithWildcard_ConvertsPlaceholdersToWildcards) that covers single placeholder, multiple/adjacent placeholders, no placeholder, and trailing %.

Validated with:

  • dotnet build src/Platform/Microsoft.Testing.Extensions.CrashDump/Microsoft.Testing.Extensions.CrashDump.csproj -c Debug – 0 warnings, 0 errors.
  • Microsoft.Testing.Extensions.UnitTests (net8.0): all 90 tests pass, including 12 CrashDumpTests (6 new placeholder cases).

When the testhost crashes alongside one or more child processes, the .NET runtime writes a separate dump for each crashing process using the configured dump file name pattern. Previously the crash-dump extension only reported the testhost's own dump (matched by PID), losing the child-process dumps.

Convert the dump file name pattern to a wildcard search pattern by replacing every '%X' placeholder with '*' and enumerate every matching file in the dump directory, publishing each one as a FileArtifact.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings May 15, 2026 17:05
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR updates the CrashDump extension to collect and publish all crash dumps produced in the configured dump directory when the testhost crashes, including dumps generated by crashing child processes (fixing #4186).

Changes:

  • Converts the configured dump filename pattern into a wildcard pattern (replacing %X placeholders with *) and publishes all matching dump files as artifacts.
  • Keeps the existing *.dmp fallback when no pattern matches, and normalizes the artifact display name used in that fallback.
  • Adds parameterized unit coverage for placeholder-to-wildcard conversion behavior.
Show a summary per file
File Description
test/UnitTests/Microsoft.Testing.Extensions.UnitTests/CrashDumpTests.cs Adds unit tests for converting dump name placeholders into wildcard search patterns.
src/Platform/Microsoft.Testing.Extensions.CrashDump/CrashDumpProcessLifetimeHandler.cs Updates dump discovery to publish all dumps matching the configured pattern and adds the placeholder-to-wildcard helper.

Copilot's findings

  • Files reviewed: 2/2 changed files
  • Comments generated: 1

Copy link
Copy Markdown
Member Author

@Evangelink Evangelink left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review Summary

# Dimension Verdict
1 Algorithmic Correctness 🔴 1 MAJOR
13 Test Completeness & Coverage 🟡 1 NIT

✅ 19/21 dimensions clean.

  • CorrectnessPath.GetDirectoryName returns "" (not null) for bare filenames, causing Directory.Exists("")false and silently skipping all file enumeration when no directory prefix is in the pattern.
  • Test Coverage — no test covers the no-directory-path case in OnTestHostProcessExitedAsync.

Key finding

Path.GetDirectoryName("dump_%p.dmp")"" on .NET Core/5+. The null-guard passes but Directory.Exists("") is false, so neither the wildcard search nor the *.dmp fallback scan executes. Fix: default to "." when the result is null-or-empty.

Generated by Expert Code Review (on open) for issue #8268 · ● 4.9M

Comment thread test/UnitTests/Microsoft.Testing.Extensions.UnitTests/CrashDumpTests.cs Outdated
Evangelink and others added 2 commits May 15, 2026 19:45
Adds CrashDump_TesthostAndChildBothCrash_CollectsAllDumps which spawns a child process from the testhost that also crashes via FailFast, then asserts both dumps end up on disk AND are reported as out-of-process file artifacts. The artifact-output assertion is what guards the #4186 fix: prior to the fix, only the testhost's own PID-matching dump was published as an artifact.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Addresses PR review feedback:

- Switch from glob pattern (Directory.EnumerateFiles searchPattern) to regex matching so that literal glob metacharacters ('*' or '?') in user-supplied dump file names (legal on Linux/macOS) are matched literally and do not cause unrelated .dmp files to be picked up.

- Treat an empty dumpDirectory (returned by Path.GetDirectoryName for a bare filename on .NET Core/5+) as '.' (current working directory) so enumeration is not silently skipped when the configured pattern has no directory prefix.

- Replace ReplaceCrashDumpPlaceholdersWithWildcard with BuildDumpFileNameRegex / BuildDumpFileNameRegexPattern, add GetDumpDirectory helper, and update unit tests to cover literal '*'/'?' in the file name and the no-directory-component case.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings May 16, 2026 08:48
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot's findings

  • Files reviewed: 3/3 changed files
  • Comments generated: 3

Copilot AI and others added 2 commits May 16, 2026 15:04
- Snapshot pre-existing files in the dump directory before the testhost starts and exclude them when publishing crash dumps, so stale dumps from previous runs that match the same pattern are no longer surfaced as artifacts.

- Use Path.GetFileName + ordinal-ignore-case comparison instead of EndsWith for the dotnet executable detection in the CrashDump test asset.

- Add a 60-second bounded WaitForExit for the spawned child process and kill it on timeout to keep acceptance tests reliable.

- Handle empty pattern in GetDumpDirectory so Path.GetDirectoryName('') no longer throws ArgumentException on .NET Framework.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings May 16, 2026 14:27
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot's findings

  • Files reviewed: 3/3 changed files
  • Comments generated: 2

// exercise the crashdump extension's ability to collect dumps from child processes.
if (Environment.GetEnvironmentVariable("CRASHDUMP_SPAWN_CHILD_THAT_CRASHES") == "1")
{
Process self = Process.GetCurrentProcess();
? $"exec \"{Assembly.GetEntryAssembly()!.Location}\" "
: string.Empty;

Process child = Process.Start(new ProcessStartInfo(path, $"{argPrefix}--child-crash")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Collect all dumps in the directory inside the crash dump

3 participants