CNA-BUG-081: Game::InactiveSleepTime is stored and validated but the loop never sleeps while the game is inactive
Evidence basis: source-verified at the pinned commit; 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.
InactiveSleepTime is documented in Game.hpp and the C API as how long the loop sleeps while the game is inactive, but nothing in Tick, RunLoop or the browser frame reads it, so an unfocused game keeps its full frame rate.
- Identifier
CNA-BUG-081- Category
- Bug
- Subsystem
- Core & runtime
- Status
- Open
- Verified against
- CNA
009d40f5(009d40f5dd085c4e674d3479675fac84b12b3e0a) - Severity
- Low (a triage suggestion, not a project priority)
- Evidence basis
- Source-verified: read at TARGET, not executed
- Tests touching this area
- Yes: see Current tests
- Affected contract
- Microsoft::Xna::Framework::Game::getInactiveSleepTimeProperty() / setInactiveSleepTimeProperty(); cna_game_get_inactive_sleep_time_ticks / cna_game_set_inactive_sleep_time_ticks
Expected behaviour
Game.hpp documents the property as “the time spent sleeping when the game is inactive”, and runtime.h as “how long the loop sleeps while the game is inactive”. XNA 4.0's Game.Tick sleeps for InactiveSleepTime whenever IsActive is false.
Actual behaviour at TARGET
InactiveSleepTime_ is initialised to 20 ms, rejected when negative (the message says “must be positive” although zero is accepted) and returned by the getter; no code reads it. Game::Tick and Game::RunLoop run at the target rate whether or not the window has focus. Only the mobile suspension path parks the thread, through WaitWhileSuspended and a fixed 16 ms delay. FNA stores the value and ignores it in the same way.
Source locations
modules/runtime/src/Game.cpp— InactiveSleepTime_ initialisation, getInactiveSleepTimeProperty/setInactiveSleepTimeProperty; no reader in Tick, RunLoop or WaitWhileSuspendedmodules/runtime/include/Microsoft/Xna/Framework/Game.hpp— Doxygen of the InactiveSleepTime accessorsmodules/c-api/include/CNA/C/runtime.h— cna_game_get_inactive_sleep_time_ticks / cna_game_set_inactive_sleep_time_ticks documentationmodules/c-api/src/CnaCApiGameProperties.cpp— C wrappers forward to the canonical accessors
Evidence
Checked by reading Game.cpp and searching every module at 009d40f5 for InactiveSleepTime: the only uses are the accessors and the C API wrappers. XNA 4.0's behaviour was read from the IL of Game.Tick. Not executed.
Independently observed as a separate finding (merged): XNA 4.0's Tick sleeps for InactiveSleepTime while the game is inactive; CNA's Tick, RunLoop and browser frame never read the value.
Focused reproduction
No focused reproduction is known. Nothing has been invented here; the evidence above is what exists.
Current tests
No test in modules/runtime/tests reads or sets InactiveSleepTime. RuntimeGameSmoke.c round-trips the value and checks the negative-value refusal through the C API only (and the C library is not built in CI).
Regression test
A runtime test with a platform decorator that counts Delay() calls: deliver a focus-lost event, run one frame and expect a delay of InactiveSleepTime; with focus regained, expect none.
Blast radius
Desktop games that lose focus keep rendering and consuming CPU and GPU at full rate; code that sets the property (through C++ or the C API) gets no effect. Mobile suspension is handled separately and is unaffected.
Workaround
Check getIsActiveProperty() in Update and sleep or skip work while it is false, or subscribe to Deactivated/Activated.
Related pages
The same subject is explained at several altitudes. These are the neighbouring pages at each one.
- User guide
- Game loop and lifecycle
- Architecture
- Runtime lifecycle: what one Tick does
- Internals
- Runtime module internals: game state
- Known issues
- Bug index