Skip to content

Prevent Test Hangs Caused By Concurrent Trace Listener Mutation - #2465

Open
Brian Robbins (brianrob) wants to merge 5 commits into
microsoft:mainfrom
brianrob:brianrob/ci-test-hang
Open

Prevent Test Hangs Caused By Concurrent Trace Listener Mutation#2465
Brian Robbins (brianrob) wants to merge 5 commits into
microsoft:mainfrom
brianrob:brianrob/ci-test-hang

Conversation

@brianrob

@brianrob Brian Robbins (brianrob) commented Sep 3, 2026

Copy link
Copy Markdown
Member

Summary

Prevent assertion dialogs from blocking test runs while preserving parallel execution.

  • Stop the ELF mismatch tests from clearing and restoring the process-wide Trace.Listeners collection.
  • Eagerly initialize the .NET Framework trace-listener configuration from a TraceEventTests module initializer before xUnit starts test methods in parallel.
  • Validate the existing listener configuration before intentionally triggering assertions; the tests do not install or repair listeners.
  • Disable interactive assertion UI in test app.config files while retaining ThrowingTraceListener.
  • Add the previously missing listener configuration to FastSerialization.Tests.

Root cause

Trace.Listeners is process-wide state and its configuration is loaded lazily. The ELF mismatch tests previously cleared and restored that collection while other tests could use it, allowing assertion tests to run with DefaultTraceListener and open an interactive assertion dialog.

Removing the explicit listener mutation fixed that race, but the full parallel TraceEventTests workload also reproduced concurrent first access to the lazily initialized listener configuration. The module initializer now forces that configuration to finish loading on one thread before any test method executes. Test parallelization remains enabled.

On .NET Framework, AssertValid() verifies that DefaultTraceListener is absent and ThrowingTraceListener was registered by the test assembly's app.config. It only inspects the collection because repairing process-wide listener state could introduce another race. Modern .NET ignores this app.config diagnostics section, but its built-in assertion behavior already throws; the assertion tests verify that behavior directly.

Validation

  • TraceEvent.Tests builds successfully for net462 and net8.0.
  • Three exact seven-assembly VSTest 18.9.0 Debug/Release stress iterations passed with TraceEvent.Tests parallelization enabled.
  • Removing the listener configuration causes the validation test to fail through xUnit within seconds instead of opening an assertion dialog.
  • Twenty consecutive public Azure DevOps PR merge-ref runs against 2acb78c01d6d3331e6b091740827b80c15dfd1e9 completed both the PerfView_Debug and PerfView_Release test tasks without a hang. Nineteen builds passed; build 1583681 completed normally but had two unrelated transient TdhEnumerateProviders test failures.

CI build IDs: 1583568, 1583609, 1583612, 1583613, 1583614, 1583615, 1583652, 1583653, 1583654, 1583655, 1583656, 1583678, 1583679, 1583680, 1583681, 1583682, 1583734, 1583735, 1583736, 1583737.

Run only the tests that mutate the process-wide Trace.Listeners collection exclusively, while preserving the assertion tests that validate ThrowingTraceListener configuration. Add a VSTest safety timeout for future hangs.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Stop tests from mutating the process-wide trace listener collection, validate the configured listener before intentional assertions, and disable assertion UI in test configurations. Serialize TraceEvent tests to avoid the listener initialization race observed under the full workload.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Document why modern .NET skips listener configuration checks and why .NET Framework validation does not repair listener state.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Describe how assertion failures throw on .NET Framework and modern .NET, and explain why listener validation must not repair process-wide state.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Eagerly load .NET Framework trace listener configuration from a module initializer before xUnit starts test methods in parallel. Remove assembly-wide TraceEvent test serialization while preserving validation-only listener checks.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
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.

1 participant