Summary
In EngineToggleStateCoordinator, a prime that completes synchronously in a non-success state can run CompletePrime's marker removal before StartPrimeIfNeeded registers that marker. A stale marker for a finished prime is then left in _primeTasks, which blocks any later re-prime for that engine. This is hazard B from the #942 research, first recorded as NB-2 in the #735 code review, and never promoted.
Environment
- OS/version: Windows 11 / windows-latest
- Python version: n/a (C#, .NET Framework 4.8)
- Command/flags used: n/a (production code path; also reachable from the re-prime in
GetPressed_WhenPrimeFaults_LogsErrorAndStillReturnsFalse)
- Data source or fixture: n/a
Steps to Reproduce
- Arrange for
EngineActiveAsync to return an already-faulted task, for example after a cached configuration-load fault.
- Call
GetPressed for that engine, which triggers StartPrimeIfNeeded.
StartObservedPrime schedules the continuation. The continuation can run CompletePrime (_primeTasks.TryRemove, line ~348) before the assignment _primeTasks[engineName] = ... at line ~276 stores it.
Expected Behavior
A finished prime never leaves a marker in _primeTasks, so a later GetPressed can start a fresh prime.
Actual Behavior
The removal can precede the registration. The marker for the completed prime then stays registered, ContainsKey returns true, and no later prime starts for that engine.
Logs / Screenshots
Impact / Severity
Source
From: docs/features/potential/2026-09-30-engine-toggle-prime-marker-registration-races-removal.md
Summary
In
EngineToggleStateCoordinator, a prime that completes synchronously in a non-success state can runCompletePrime's marker removal beforeStartPrimeIfNeededregisters that marker. A stale marker for a finished prime is then left in_primeTasks, which blocks any later re-prime for that engine. This is hazard B from the #942 research, first recorded as NB-2 in the #735 code review, and never promoted.Environment
GetPressed_WhenPrimeFaults_LogsErrorAndStillReturnsFalse)Steps to Reproduce
EngineActiveAsyncto return an already-faulted task, for example after a cached configuration-load fault.GetPressedfor that engine, which triggersStartPrimeIfNeeded.StartObservedPrimeschedules the continuation. The continuation can runCompletePrime(_primeTasks.TryRemove, line ~348) before the assignment_primeTasks[engineName] = ...at line ~276 stores it.Expected Behavior
A finished prime never leaves a marker in
_primeTasks, so a laterGetPressedcan start a fresh prime.Actual Behavior
The removal can precede the registration. The marker for the completed prime then stays registered,
ContainsKeyreturns true, and no later prime starts for that engine.Logs / Screenshots
docs/features/active/2026-09-29-engine-toggle-prime-fault-logging-test-races-942/research/2026-09-29T23-20-engine-toggle-prime-fault-race-research.md, conclusion 3.Impact / Severity
Source
From: docs/features/potential/2026-09-30-engine-toggle-prime-marker-registration-races-removal.md