CNA-BUG-207: Delta-maintained diagnostics gauges such as Audio/AllocatedVoices drift after a runtime OFF window
Evidence basis: source-verified at the pinned commit; executed for this entry (the Evidence section names exactly what was run); tests exist (not executed for this page). Claims on this page were checked by reading the CNA source at commit 009d40f5; unless a sentence says otherwise, nothing here was built or executed. Nothing on this page was executed unless the Evidence section says so.
GaugeHandle::Add discards deltas while the runtime mode is OFF, so a gauge kept with GAUGE_ADD(+1/-1), such as Audio/AllocatedVoices, stays wrong (too high, or negative) after statistics are re-enabled, until mixer shutdown resets it.
- Identifier
CNA-BUG-207- Category
- Bug
- Subsystem
- Diagnostics & Inspector
- Status
- Open
- Verified against
- CNA
009d40f5(009d40f5dd085c4e674d3479675fac84b12b3e0a) - Severity
- Low (a triage suggestion, not a project priority)
- Evidence basis
- Reproduced: executed for this entry (the Evidence section names exactly what was run)
- Tests touching this area
- Yes: see Current tests
- Affected contract
- CNA::Diagnostics::GaugeHandle::Add and CNA_DIAGNOSTICS_GAUGE_ADD across SetRuntimeMode(Mode::Off); the documented meaning of Audio/AllocatedVoices
Expected behaviour
docs/diagnostics.md: gauges retain the latest value, and Audio/AllocatedVoices is a “gauge, exact at the mixer facade” counting “mixer tracks CNA has allocated and not logically destroyed”. After statistics are re-enabled an exact gauge reports the true count, or the limitation is documented as it is for resources created while OFF.
Actual behaviour at TARGET
AddMetric and SetMetric return without writing while the runtime mode is OFF. Both mixer back-ends maintain the gauge with deltas, +1 in CreateMixerTrack and −1 in DestroyMixerTrack, and only EndMixerEngineShutdown sets it to 0. A track created before an OFF window and destroyed during it leaves the gauge one too high; one created during it and destroyed afterwards leaves it at −1. Nothing resynchronises the value, and the known-limitations list names only the resource-registry effect.
Source locations
modules/diagnostics/src/Diagnostics.cpp— AddMetric and SetMetric ignore updates in Mode::Off; GaugeHandle::Addmodules/diagnostics/include/CNA/Diagnostics/Instrumentation.hpp— CNA_DIAGNOSTICS_GAUGE_ADDmodules/audio/src/Backend/CnaMixer/MixerEngine.cpp— CreateMixerTrack, DestroyMixerTrack, EndMixerEngineShutdownmodules/audio/src/Backend/Sdl3Mixer/MixerEngine.cpp— CreateMixerTrack, DestroyMixerTrack, EndMixerEngineShutdowndocs/diagnostics.md— Audio/AllocatedVoices row and Known limitationsmodules/diagnostics/tests/CNA/Diagnostics/DiagnosticsTests.cpp— OffStatsAndFullTransitionsPreserveMetricSemantics uses a counter only
Evidence
Read at 009d40f5. Executed: TARGET's Diagnostics.cpp compiled unchanged with g++ 14.2 -std=c++23 -DCNA_DIAGNOSTICS_LEVEL=2 (it needs only the standard library) and linked into a driver that uses GaugeHandle directly: +1 in STATS, −1 while OFF, back to STATS gives 1; +1 while OFF, −1 in STATS gives −1; the live count is 0 in both. The mixer paths were not run; that they use ±1 deltas is by reading.
Focused reproduction
Compiled and run as described under Evidence.
using namespace CNA::Diagnostics;
(void)SetRuntimeMode(Mode::Stats);
GaugeHandle voices("Probe/AllocatedVoices");
voices.Add(1); // a track is created
(void)SetRuntimeMode(Mode::Off);
voices.Add(-1); // ...and destroyed while OFF: discarded
(void)SetRuntimeMode(Mode::Stats);
// GetProvider().CaptureSnapshot() reports Probe/AllocatedVoices == 1; nothing is allocated.
Current tests
OffStatsAndFullTransitionsPreserveMetricSemantics asserts that a counter drops OFF-window adds; AudioDiagnosticsTests VoiceGaugeAndCreationCounterTrackExactLifecycle checks the gauge without a mode change. Both compile only at STATS or FULL, which no CI configuration selects.
Regression test
Create a mixer track in STATS, switch to OFF, destroy it, switch back and expect Audio/AllocatedVoices to read 0 (or to be reported with Accuracy::Unavailable until resynchronised).
Blast radius
Audio/AllocatedVoices and any application gauge maintained with GAUGE_ADD, as shown by snapshots and the Inspector's Audio and Performance views, in STATS/FULL builds that lower the runtime mode to OFF. Counters, frame counters and GAUGE_SET gauges are unaffected.
Workaround
Maintain such a gauge with CNA_DIAGNOSTICS_GAUGE_SET from an authoritative count, or do not lower the runtime mode to OFF while the value matters.
Related pages
The same subject is explained at several altitudes. These are the neighbouring pages at each one.
- Internals
- Diagnostics internals: process state
- Known issues
- Bug index