fix(engine): isolate per-session state under MTP server-mode concurrency (#6001) by thomhurst · Pull Request #6025 · thomhurst/TUnit (original) (raw)

@thomhurst

…ncy (#6001)

Concurrent testing/runTests RPCs against one long-lived MTP test process were producing zero results from sessions that should produce ~100. Root causes were shared mutable state across sessions/calls rather than a single race:

Adds TUnit.RpcTests coverage:

[claude[bot]](/apps/claude)

@thomhurst

[claude[bot]](/apps/claude)

@thomhurst

[claude[bot]](/apps/claude)

[claude[bot]](/apps/claude)

@thomhurst

Addresses PR review finding 4 (static guard + instance dependency mismatch in TUnitInitializer). Lift process-once concerns — global exception handlers, the throw-on-trace-assert listener, and test parameter parsing — out of the per-session TUnitInitializer into a dedicated static type whose name makes the lifetime obvious.

TUnitInitializer now does only session-scoped work and delegates explicit ICommandLineOptions to the process initializer. The static flag for parameter parsing is gone; the per-instance guard left in TUnitInitializer protects only concurrent ExecuteRequestAsync calls within a single session, which is its actual job.

@thomhurst

…zers

Three call sites had the same wait-on-first-caller pattern, and two of them (TUnitProcessInitializer.EnsureInitialised and TUnitInitializer._sessionInitialised) were still set-flag-then-work — the very race we just fixed downstream in ReflectionHookDiscoveryService. Concurrent callers could short-circuit past partial initialization and read TestContext.InternalParametersDictionary or Sources.* before the producing caller finished populating them.

[claude[bot]](/apps/claude)

This was referenced

Jun 13, 2026

This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.Learn more about bidirectional Unicode characters

[ Show hidden characters]({{ revealButtonHref }})