CNA-BUG-266: GamerServicesDispatcher::Initialize re-initialises silently when gamer services are already initialised, where XNA 4.0 throws InvalidOperationException
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.
XNA 4.0's GamerServicesDispatcher.Initialize throws InvalidOperationException (GamerServicesAlreadyInitialized) when IsInitialized is true; CNA's Initialize follows FNA, frees the earlier stub gamers and installs four new ones, so a second call succeeds.
- Identifier
CNA-BUG-266- Category
- Bug
- Subsystem
- Networking & gamer services
- 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::GamerServices::GamerServicesDispatcher::Initialize(System::IServiceProvider&)
Expected behaviour
XNA 4.0 (read from the decompiled genuine Microsoft.Xna.Framework.GamerServices assembly) begins GamerServicesDispatcher.Initialize with if (IsInitialized) throw new InvalidOperationException(GamerServicesAlreadyInitialized), so initialising twice is a programming error that is reported. CNA's rule is that XNA 4.0 wins where FNA and XNA disagree.
Actual behaviour at TARGET
GamerServicesDispatcher::Initialize sets isInitialized_ without checking it, frees the previous call's stub gamers and installs four new ones; its comment records that a second call used to leak the first call's gamers and now frees them, so re-initialisation is treated as a supported path. A game that creates a GamerServicesComponent and also calls Initialize itself, or two components, therefore gets no exception where an XNA program would.
Source locations
modules/gamer-services/src/Xna/GamerServicesDispatcher.cpp— Initialize: no already-initialised check; frees and rebuilds the stub gamers
Evidence
Read at 009d40f5 against the decompiled XNA 4.0 GamerServicesDispatcher.Initialize; nothing was executed. Noted by the D4 dismissal reviewer outside its candidates and re-verified by the orchestrator. CNA-BUG-166 covers what the re-initialisation deletes; this entry covers the missing exception.
Independent re-verification: XNA's GamerServicesComponent.Initialize calls GamerServicesDispatcher.Initialize unguarded, so two components throw in XNA too; the documented exception is InvalidOperationException (“the gamer services functionality is already initialized”).
Focused reproduction
No focused reproduction is known. Nothing has been invented here; the evidence above is what exists.
Current tests
One CNA test pins the opposite behaviour: GamerServicesDispatcherHangRegressionTest.SecondInitializeDoesNotLeakThePreviousFourGamers runs the dispatcher harness in --mode=initialize-leak-check, which calls Initialize a second time and requires it to succeed and free the four earlier gamers; no test asserts that a second call throws. A fix has to rewrite that test as well as add the check.
Regression test
Call GamerServicesDispatcher::Initialize twice and expect InvalidOperationException on the second call (and adjust the code that relies on re-initialisation).
Blast radius
XNA programs that initialise gamer services twice by mistake are not told; a program that relied on the exception to detect double initialisation behaves differently. Single initialisation, the normal case, is unaffected.
Workaround
Initialise gamer services exactly once (for example only through a GamerServicesComponent).
Related pages
The same subject is explained at several altitudes. These are the neighbouring pages at each one.
- Deep dives
- GamerServices contract
- Known issues
- Bug index