Skip to content

Detect async void lambdas in AsyncVoidAnalyzer (TUnit0031)#4758

Merged
thomhurst merged 2 commits intomainfrom
copilot/fix-concurrency-bug-mtp
Feb 13, 2026
Merged

Detect async void lambdas in AsyncVoidAnalyzer (TUnit0031)#4758
thomhurst merged 2 commits intomainfrom
copilot/fix-concurrency-bug-mtp

Conversation

Copy link
Contributor

Copilot AI commented Feb 13, 2026

The existing AsyncVoidAnalyzer only flagged async void methods via symbol analysis, missing async void lambdas and anonymous delegates. These silently swallow exceptions on the thread pool, causing SemaphoreFullException crashes when the unhandled exception races with ExecuteRequestContext.Complete().

// Previously undetected — now raises TUnit0031
Action action = async () => {
    await SomethingAsync(); // exception here crashes the process
};

Changes

  • AsyncVoidAnalyzer.cs — Added RegisterSyntaxNodeAction for ParenthesizedLambdaExpression, SimpleLambdaExpression, and AnonymousMethodExpression. Resolves the lambda's IMethodSymbol via semantic model to check ReturnsVoid.
  • Resources.resx / Resources.Designer.cs — Diagnostic message updated to "Async void methods and lambdas are not allowed".
  • AsyncVoidAnalyzerTests.cs — Five new test cases: parenthesized lambda, simple lambda, parameterized lambda, anonymous delegate, and a Func<Task> negative case.
Original prompt

This section details on the original issue you should resolve

<issue_title>[Bug]: concurrency bug with Microsoft.Testing.Platform</issue_title>
<issue_description>### Description

Running dotnet test (enabled MTP in global.json). It crashes in one specific project in the solution and in no others. I didn't manage to find the difference between this and other projects in the way we have set up tests.

Expected Behavior

Well, not to crash.

Actual Behavior

I am getting the same crash in dotnet test, VS 2026, and Rider 2026.1 EAP 3.
Noticing that if I run a smaller number of tests, it will run as expected. Increasing the number of tests running in parallel will sometimes have all test passing, sometimes trigger this crash. Selecting even more tests to run in parallel will reliably crash TUnit every time.
The same is happening with the latest v1.13.56, as was with v1.12.139.

Steps to Reproduce

Running dotnet test on solution, or running "Run all tests" on my Parser.MySql.UnitTests project.

TUnit Version

1.13.56

.NET Version

.NET 10.0

Operating System

Windows

IDE / Test Runner

JetBrains Rider

Error Output / Stack Trace

src\Semantic\Parser.UnitTests\MySql\bin\Debug\net10.0\Parser.MySql.UnitTests.dll (net10.0|x64) failed (3s 653ms)
Exit code: -532462766
  Error output: Unhandled exception. TUnit.Assertions.Exceptions.AssertionException: Expected to be empty, because Syntax error at offset 6, line 1 --> @gvar=1
  but collection contains items: [6-13 (7 chars)]

  at Assert.That(unit.SyntaxErrors).IsEmpty().Because("Syntax error at offset 6, line 1 --> @gvar=1")
     at TUnit.Assertions.Core.Assertion`1.ThrowOrAccumulateFailure(AssertionResult result)
     at TUnit.Assertions.Core.Assertion`1.ExecuteCoreAsync()
     at TUnit.Assertions.Core.Assertion`1.AssertAsync()
     at Parser.MySql.UnitTests.BaseMySqlLexerTests.GetStatementsAsync(String script) in C:\Dev\Tests\src\Semantic\Parser.UnitTests\MySql\BaseMySqlLexerTests.cs:line 39
     at Parser.MySql.UnitTests.BaseMySqlLexerTests.GetStatementAsync[T](String script) in C:\Dev\Tests\src\Semantic\Parser.UnitTests\MySql\BaseMySqlLexerTests.cs:line 25
     at Parser.MySql.UnitTests.Statements.IdentifierTest.<InvalidVar>b__2_0() in C:\Dev\Tests\src\Semantic\Parser.UnitTests\MySql\Statements\Identifier.cs:line 29
     at System.Threading.Tasks.Task.<>c.<ThrowAsync>b__124_1(Object state)
     at System.Threading.QueueUserWorkItemCallback.Execute()
     at System.Threading.ThreadPoolWorkQueue.Dispatch()
     at System.Threading.PortableThreadPool.WorkerThread.WorkerThreadStart()
     at System.Threading.Thread.StartCallback()
  Unhandled exception. System.Threading.SemaphoreFullException: Adding the specified count to the semaphore would cause it to exceed its maximum count.
     at System.Threading.SemaphoreSlim.Release(Int32 releaseCount)
     at Microsoft.Testing.Platform.Requests.SemaphoreSlimRequestCompleteNotifier.Complete() in /_/src/Platform/Microsoft.Testing.Platform/Requests/SemaphoreSlimRequestCompleteNotifier.cs:line 14
     at Microsoft.Testing.Platform.Extensions.TestFramework.ExecuteRequestContext.Complete() in /_/src/Platform/Microsoft.Testing.Platform/TestFramework/ExecuteRequestContext.cs:line 55
     at TUnit.Engine.Framework.TUnitTestFramework.ExecuteRequestAsync(ExecuteRequestContext context)
     at TUnit.Engine.Framework.TUnitTestFramework.ExecuteRequestAsync(ExecuteRequestContext context)
     at Microsoft.Testing.Platform.Requests.TestHostTestFrameworkInvoker.ExecuteRequestAsync(ITestFramework testFramework, TestExecutionRequest request, IMessageBus messageBus, CancellationToken cancellationToken) in /_/src/Platform/Microsoft.Testing.Platform/Requests/TestHostTestFrameworkInvoker.cs:line 92
     at Microsoft.Testing.Platform.Requests.TestHostTestFrameworkInvoker.ExecuteAsync(ITestFramework testFramework, ClientInfo client, CancellationToken cancellationToken) in /_/src/Platform/Microsoft.Testing.Platform/Requests/TestHostTestFrameworkInvoker.cs:line 73
     at Microsoft.Testing.Platform.Hosts.CommonHost.ExecuteRequestAsync(ProxyOutputDevice outputDevice, ITestSessionContext testSessionInfo, ServiceProvider serviceProvider, BaseMessageBus baseMessageBus, ITestFramework testFramework, ClientInfo client) in /_/src/Platform/Microsoft.Testing.Platform/Hosts/CommonTestHost.cs:line 166
     at Microsoft.Testing.Platform.Hosts.ConsoleTestHost.InternalRunAsync(CancellationToken cancellationToken) in /_/src/Platform/Microsoft.Testing.Platform/Hosts/ConsoleTestHost.cs:line 85
     at Microsoft.Testing.Platform.Hosts.ConsoleTestHost.InternalRunAsync(CancellationToken cancellationToken) in /_/src/Platform/Microsoft.Testing.Platform/Hosts/ConsoleTestHost.cs:line 117
     at Microsoft.Testing.Platform.Hosts.CommonHost.RunTestAppAsync(IPlatformOpenTelemetryService platformOTelService, CancellationToken testApplicationCancellationToken) in /_/src/Platform/Microsoft.Testing.Platform/Hosts/CommonTestH...

</details>



<!-- START COPILOT CODING AGENT SUFFIX -->

- Fixes thomhurst/TUnit#4756

<!-- START COPILOT CODING AGENT TIPS -->
---

💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more [Copilot coding agent tips](https://gh.io/copilot-coding-agent-tips) in the docs.

…delegates

Co-authored-by: thomhurst <30480171+thomhurst@users.noreply.github.com>
Copilot AI changed the title [WIP] Fix concurrency bug with Microsoft.Testing.Platform Detect async void lambdas in AsyncVoidAnalyzer (TUnit0031) Feb 13, 2026
Copilot AI requested a review from thomhurst February 13, 2026 19:18
@thomhurst thomhurst marked this pull request as ready for review February 13, 2026 19:21
@thomhurst thomhurst enabled auto-merge (squash) February 13, 2026 19:22
@thomhurst thomhurst linked an issue Feb 13, 2026 that may be closed by this pull request
1 task
@claude
Copy link
Contributor

claude bot commented Feb 13, 2026

Code review

No issues found. Checked for bugs and CLAUDE.md compliance.

This PR effectively addresses a critical gap in the AsyncVoidAnalyzer by extending detection to async void lambdas and anonymous delegates. The implementation:

  • Correctly uses Roslyn syntax node analysis for all lambda expression types
  • Includes comprehensive test coverage (5 new test cases)
  • Follows existing analyzer patterns in the codebase
  • Properly handles edge cases (null symbols, non-async lambdas)

The fix resolves the SemaphoreFullException crashes that were occurring in concurrent test scenarios when async void lambdas silently swallowed exceptions.

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.

[Bug]: concurrency bug with Microsoft.Testing.Platform

2 participants