CNA-BUG-220: cna_game_destroy's comment says Shutdown has disposed the canonical graphics device; it has not
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.
A comment in cna_game_destroy claims CGame::Shutdown already disposed the game's canonical GraphicsDevice so C subscribers saw its Disposing event, but Game::Dispose(true) never disposes the Game-owned device.
- Identifier
CNA-BUG-220- Category
- Bug
- Subsystem
- Documentation & release tooling
- 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
- cna_game_destroy teardown order (maintainer documentation in CnaCApiRuntime.cpp)
Expected behaviour
The comment that explains why the C-side device adapter state may be dropped states the real order: the canonical device is disposed only when the game object is destroyed, after the handle is released.
Actual behaviour at TARGET
After game->Shutdown() the comment reads “Shutdown has already disposed the canonical graphics device, so any C subscriber has observed its Disposing event”. CGame::Shutdown calls Game::Dispose(), and Game::Dispose(true) disposes components, the content manager and the registered IGraphicsDeviceService; GraphicsDeviceManager::Dispose(true) raises its own DeviceDisposing but never disposes a Game-owned device. The canonical GraphicsDevice raises Disposing from its destructor, after the adapter state has already been reset. The comment on ResetGraphicsDeviceAdapterState in modules/c-api/src/CnaCApiRuntimeDetail.hpp repeats the premise (the game-destroy path calls it "once the canonical device has already raised its own Disposing event").
Source locations
modules/c-api/src/CnaCApiRuntime.cpp— cna_game_destroy comment after the Shutdown call; CGame::Shutdownmodules/c-api/src/CnaCApiRuntimeDetail.hpp— the comment on ResetGraphicsDeviceAdapterState repeats the premisemodules/runtime/src/Game.cpp— Game::Dispose(bool) does not dispose GraphicsDevice_modules/runtime/src/GraphicsDeviceManager.cpp— GraphicsDeviceManager::Dispose(bool): delete only when ownsGraphicsDevice_modules/c-api/include/CNA/C/graphics_device.h— device event registrations must be released before cna_game_destroy succeeds
Evidence
Checked by reading CnaCApiRuntime.cpp, Game.cpp and GraphicsDeviceManager.cpp at 009d40f5. The C API was not built or run. Because graphics_device.h requires device event registrations to be released before cna_game_destroy succeeds, no live C subscriber is known to be affected; whether a C caller can ever observe the canonical device's Disposing event was not established.
Focused reproduction
No focused reproduction is known. Nothing has been invented here; the evidence above is what exists.
Current tests
The C API runtime tests (not built in CI) exercise cna_game_destroy; none asserts on the canonical device's Disposing event.
Regression test
Correct the comment; if the C API is meant to deliver the canonical device's Disposing event, add a C test that subscribes, destroys the game and expects exactly one callback.
Blast radius
Maintainers of the C API teardown path; no behaviour is known to depend on the false statement.
Workaround
No workaround is known.
Related pages
The same subject is explained at several altitudes. These are the neighbouring pages at each one.
- User guide
- C API: the model
- Internals
- C API internals: what cna_game_destroy does, in order · Ownership and shutdown: exit versus dispose versus destructor
- Maintainer workflow
- Ownership and lifetime master map: foreign-function interfaces
- Known issues
- Bug index