Skip to content

Fix MSTest live output deadlock#10169

Merged
Evangelink merged 4 commits into
mainfrom
dev/amauryleve/fix-mstest-live-deadlock
Jul 23, 2026
Merged

Fix MSTest live output deadlock#10169
Evangelink merged 4 commits into
mainfrom
dev/amauryleve/fix-mstest-live-deadlock

Conversation

@Evangelink

Copy link
Copy Markdown
Member

Summary

  • route TestContext and trace live echoes through a dedicated synchronized writer over standard output
  • preserve console encoding without writing an encoding preamble, auto-flush live output, and keep the process-owned stream open
  • add a deterministic regression that reproduces the captured/current Console.Out lock inversion and verifies concurrent writes complete with the dedicated writer

Root cause

Linux Helix dumps from dotnet/sdk showed TestContextImplementation.WriteLive holding the originally captured synchronized writer while ConsolePal.WriteFromConsoleStream waited for the current Console.Out. Concurrently, the console logger held the current Console.Out writer while ConsoleRouter waited for the captured writer. This opposing lock order deadlocked all live-output writers.

The dedicated writer removes the captured writer from the TestContext and trace paths. Console stdout/stderr routers retain their existing captured-writer behavior, preserving None, Result, Live, redirection, and install-once semantics without introducing the inverse lock order.

Unblocks dotnet/sdk#55418.

Validation

  • adapter platform-services unit-test project built across all configured TFMs with 0 warnings/errors
  • ConsoleRouterTests: 10/10 passed
  • deadlock regression: 25/25 repeated runs passed
  • OutputCaptureModeTests acceptance suite: 14/14 passed
  • Debug package build: 0 warnings/errors

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 893d0fed-d2f1-4c47-a0e8-9648c457af66
Copilot AI review requested due to automatic review settings July 23, 2026 09:49

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Fixes MSTest live-output deadlocks by separating live echoes from the captured console writer.

Changes:

  • Adds a synchronized, auto-flushing standard-output writer without encoding preambles.
  • Routes TestContext and trace live output through the dedicated writer.
  • Adds a deterministic lock-inversion regression test.
Show a summary per file
File Description
UnitTestRunner.cs Creates and configures the dedicated live-output writer.
InternalAPI.Unshipped.txt Tracks the new internal writer factory.
ConsoleRouterTests.cs Verifies deadlock prevention and writer behavior.

Review details

  • Files reviewed: 3/3 changed files
  • Comments generated: 0
  • Review effort level: Medium

@github-actions

This comment has been minimized.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 893d0fed-d2f1-4c47-a0e8-9648c457af66
Copilot AI review requested due to automatic review settings July 23, 2026 10:11

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Review details

  • Files reviewed: 3/3 changed files
  • Comments generated: 1
  • Review effort level: Medium

@github-actions

This comment has been minimized.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 893d0fed-d2f1-4c47-a0e8-9648c457af66
Copilot AI review requested due to automatic review settings July 23, 2026 10:47

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Review details

Comments suppressed due to low confidence (1)

test/UnitTests/MSTestAdapter.PlatformServices.UnitTests/Execution/ConsoleRouterTests.cs:268

  • As in the other regression test, restoring the live writer to previousConsoleOut corrupts the install-once routing state when that value is already the console router. A later live-output context can then use the captured writer and regain the lock inversion. Preserve and restore the exact previous live writer instead of deriving it from Console.Out.
            TestContextImplementation.ConfigureLiveOutputWriter(previousConsoleOut);
  • Files reviewed: 3/3 changed files
  • Comments generated: 1
  • Review effort level: Medium

@github-actions

This comment has been minimized.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 893d0fed-d2f1-4c47-a0e8-9648c457af66
Copilot AI review requested due to automatic review settings July 23, 2026 11:14

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Review details

  • Files reviewed: 4/4 changed files
  • Comments generated: 0 new
  • Review effort level: Medium

@github-actions

Copy link
Copy Markdown
Contributor

🧪 Test quality grade — PR #10169

GradeTestNotes
B (80–89) new ConsoleRouterTests.
LiveOutput_
ConcurrentTestContextAndConsoleWrites_
DoNotInvertConsoleWriterLocks
Six rich assertions covering lock-inversion, message content, output, and BOM; ~50-line body with two scenarios — consider splitting the prove-the-bug and prove-the-fix halves into separate tests.
B (80–89) new ConsoleRouterTests.
LiveOutputWriterScope_
RestoresPreviousWriter
Clear assertions on both writers with positive and negative content checks; ~50-line body — consider extracting the nested-scope arrangement into a helper method.
B (80–89) new ConsoleRouterTests.
LiveTrace_
ConcurrentTraceAndConsoleWrites_
DoNotInvertConsoleWriterLocks
Mirrors the LiveOutput test for the trace path with solid lock-inversion and output assertions; ~50-line body — consider splitting the two scenarios as above.

This advisory comment was generated automatically. Grades are heuristic
and informational — they do not block merging. Re-run with
/grade-tests.

Warning

Firewall blocked 1 domain

The following domain was blocked by the firewall during workflow execution:

  • awmgmcpg

To allow these domains, add them to the network.allowed list in your workflow frontmatter:

network:
  allowed:
    - defaults
    - "awmgmcpg"

See Network Configuration for more information.

🤖 Automated content by GitHub Copilot. Generated by the Grade Tests on PR (on open / sync) workflow. · 51.5 AIC · ⌖ 7.38 AIC · ⊞ 8.9K · [◷]( · )

@Evangelink

Copy link
Copy Markdown
Member Author

/azp run

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
Successfully started running 1 pipeline(s).

@Evangelink Evangelink added the state/needs-review Awaiting review from the team. label Jul 23, 2026
@Evangelink
Evangelink enabled auto-merge (squash) July 23, 2026 13:12
@Evangelink
Evangelink merged commit 550b853 into main Jul 23, 2026
33 checks passed
@Evangelink
Evangelink deleted the dev/amauryleve/fix-mstest-live-deadlock branch July 23, 2026 13:25
@Evangelink

Copy link
Copy Markdown
Member Author

/backport to rel/4.3

@github-actions

Copy link
Copy Markdown
Contributor

Started backporting to rel/4.3: https://github.com/microsoft/testfx/actions/runs/30012136008

@github-actions

Copy link
Copy Markdown
Contributor

@Evangelink backporting to rel/4.3 failed, the patch most likely resulted in conflicts:

$ git am --3way --empty=keep --ignore-whitespace --keep-non-patch changes.patch

Patch format detection failed.
Error: The process '/usr/bin/git' failed with exit code 128

NOTE: A PR will be created, but needs to be revised manually!

@github-actions

Copy link
Copy Markdown
Contributor

@Evangelink backporting to rel/4.3 failed, the patch most likely resulted in conflicts:

$ git am --continue

fatal: Resolve operation not in progress, we are not resuming.
Error: The process '/usr/bin/git' failed with exit code 128

NOTE: A PR will be created, but needs to be revised manually!

17 similar comments
@github-actions

Copy link
Copy Markdown
Contributor

@Evangelink backporting to rel/4.3 failed, the patch most likely resulted in conflicts:

$ git am --continue

fatal: Resolve operation not in progress, we are not resuming.
Error: The process '/usr/bin/git' failed with exit code 128

NOTE: A PR will be created, but needs to be revised manually!

@github-actions

Copy link
Copy Markdown
Contributor

@Evangelink backporting to rel/4.3 failed, the patch most likely resulted in conflicts:

$ git am --continue

fatal: Resolve operation not in progress, we are not resuming.
Error: The process '/usr/bin/git' failed with exit code 128

NOTE: A PR will be created, but needs to be revised manually!

@github-actions

Copy link
Copy Markdown
Contributor

@Evangelink backporting to rel/4.3 failed, the patch most likely resulted in conflicts:

$ git am --continue

fatal: Resolve operation not in progress, we are not resuming.
Error: The process '/usr/bin/git' failed with exit code 128

NOTE: A PR will be created, but needs to be revised manually!

@github-actions

Copy link
Copy Markdown
Contributor

@Evangelink backporting to rel/4.3 failed, the patch most likely resulted in conflicts:

$ git am --continue

fatal: Resolve operation not in progress, we are not resuming.
Error: The process '/usr/bin/git' failed with exit code 128

NOTE: A PR will be created, but needs to be revised manually!

@github-actions

Copy link
Copy Markdown
Contributor

@Evangelink backporting to rel/4.3 failed, the patch most likely resulted in conflicts:

$ git am --continue

fatal: Resolve operation not in progress, we are not resuming.
Error: The process '/usr/bin/git' failed with exit code 128

NOTE: A PR will be created, but needs to be revised manually!

@github-actions

Copy link
Copy Markdown
Contributor

@Evangelink backporting to rel/4.3 failed, the patch most likely resulted in conflicts:

$ git am --continue

fatal: Resolve operation not in progress, we are not resuming.
Error: The process '/usr/bin/git' failed with exit code 128

NOTE: A PR will be created, but needs to be revised manually!

@github-actions

Copy link
Copy Markdown
Contributor

@Evangelink backporting to rel/4.3 failed, the patch most likely resulted in conflicts:

$ git am --continue

fatal: Resolve operation not in progress, we are not resuming.
Error: The process '/usr/bin/git' failed with exit code 128

NOTE: A PR will be created, but needs to be revised manually!

@github-actions

Copy link
Copy Markdown
Contributor

@Evangelink backporting to rel/4.3 failed, the patch most likely resulted in conflicts:

$ git am --continue

fatal: Resolve operation not in progress, we are not resuming.
Error: The process '/usr/bin/git' failed with exit code 128

NOTE: A PR will be created, but needs to be revised manually!

@github-actions

Copy link
Copy Markdown
Contributor

@Evangelink backporting to rel/4.3 failed, the patch most likely resulted in conflicts:

$ git am --continue

fatal: Resolve operation not in progress, we are not resuming.
Error: The process '/usr/bin/git' failed with exit code 128

NOTE: A PR will be created, but needs to be revised manually!

@github-actions

Copy link
Copy Markdown
Contributor

@Evangelink backporting to rel/4.3 failed, the patch most likely resulted in conflicts:

$ git am --continue

fatal: Resolve operation not in progress, we are not resuming.
Error: The process '/usr/bin/git' failed with exit code 128

NOTE: A PR will be created, but needs to be revised manually!

@github-actions

Copy link
Copy Markdown
Contributor

@Evangelink backporting to rel/4.3 failed, the patch most likely resulted in conflicts:

$ git am --continue

fatal: Resolve operation not in progress, we are not resuming.
Error: The process '/usr/bin/git' failed with exit code 128

NOTE: A PR will be created, but needs to be revised manually!

@github-actions

Copy link
Copy Markdown
Contributor

@Evangelink backporting to rel/4.3 failed, the patch most likely resulted in conflicts:

$ git am --continue

fatal: Resolve operation not in progress, we are not resuming.
Error: The process '/usr/bin/git' failed with exit code 128

NOTE: A PR will be created, but needs to be revised manually!

@github-actions

Copy link
Copy Markdown
Contributor

@Evangelink backporting to rel/4.3 failed, the patch most likely resulted in conflicts:

$ git am --continue

fatal: Resolve operation not in progress, we are not resuming.
Error: The process '/usr/bin/git' failed with exit code 128

NOTE: A PR will be created, but needs to be revised manually!

@github-actions

Copy link
Copy Markdown
Contributor

@Evangelink backporting to rel/4.3 failed, the patch most likely resulted in conflicts:

$ git am --continue

fatal: Resolve operation not in progress, we are not resuming.
Error: The process '/usr/bin/git' failed with exit code 128

NOTE: A PR will be created, but needs to be revised manually!

@github-actions

Copy link
Copy Markdown
Contributor

@Evangelink backporting to rel/4.3 failed, the patch most likely resulted in conflicts:

$ git am --continue

fatal: Resolve operation not in progress, we are not resuming.
Error: The process '/usr/bin/git' failed with exit code 128

NOTE: A PR will be created, but needs to be revised manually!

@github-actions

Copy link
Copy Markdown
Contributor

@Evangelink backporting to rel/4.3 failed, the patch most likely resulted in conflicts:

$ git am --continue

fatal: Resolve operation not in progress, we are not resuming.
Error: The process '/usr/bin/git' failed with exit code 128

NOTE: A PR will be created, but needs to be revised manually!

@github-actions

Copy link
Copy Markdown
Contributor

@Evangelink backporting to rel/4.3 failed, the patch most likely resulted in conflicts:

$ git am --continue

fatal: Resolve operation not in progress, we are not resuming.
Error: The process '/usr/bin/git' failed with exit code 128

NOTE: A PR will be created, but needs to be revised manually!

@github-actions

Copy link
Copy Markdown
Contributor

Potential infinite loop guard hit. Stopping

Evangelink added a commit to Evangelink/sdk that referenced this pull request Jul 23, 2026
Update MSTest and Microsoft.Testing.Platform to TestFX build 324182, which includes microsoft/testfx#10169, and re-enable live capture in CI.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 8bf6402b-2114-4555-97d4-9708f64b60da
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

state/needs-review Awaiting review from the team.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants