CNA-BUG-141: MediaPlayer::ProgramExit is documented as called at application exit, but nothing in CNA calls it

CNA snapshot 009d40f5  ·  Known Issues › Current bugs  ·  source links pinned to 009d40f5

✓

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.

Unlike FNA, which hooks ProcessExit, CNA never calls MediaPlayer::ProgramExit outside an explicit C API export, so the music track is not released by CNA at exit and the header's statement is false.

Identifier
CNA-BUG-141
Category
Bug
Subsystem
Audio & media
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
MediaPlayer::ProgramExit() (CNAEXT) and the release of MediaPlayer's music track at exit

Expected behaviour

MediaPlayer.hpp: “Releases renderer media resources if initialized. Called at application exit.” FNA's MediaPlayer static constructor registers ProgramExit on AppDomain.CurrentDomain.ProcessExit.

Actual behaviour at TARGET

No Game shutdown path, static destructor or atexit handler calls it; within the modules the only caller is the C API export cna_media_player_program_exit_ext in CnaCApiMediaPlayer.cpp. Unless the game stops the music itself, the music track (a raw pointer in MediaPlayer.cpp) is therefore not destroyed at exit, and the namespace-scope music audio is released during static destruction in an order unspecified relative to the mixer's own statics. When a host does call ProgramExit, it destroys the track but leaves the state Playing. No crash was traced to this; the defect is the missing exit hook the header promises.

Source locations

Evidence

Checked by reading at 009d40f5; caller search over modules and tools excluding tests. FNA read at FNA-XNA/FNA b3551247. Not executed; no exit-time failure was observed or reproduced.

Independent re-verification: Checked by reading at 009d40f5; caller search over modules, tools and tests. The only test that calls ProgramExit is the pure-C smoke test MediaPlayerSmoke.c, which calls cna_media_player_program_exit_ext as an ordinary call after earlier plays and only requires CNA_RESULT_SUCCESS; no test checks that the music track is released, that the state changes, or that an exit hook exists. FNA read at FNA-XNA/FNA b3551247. Not executed; no exit-time failure was observed or reproduced.

Focused reproduction

No focused reproduction is known. Nothing has been invented here; the evidence above is what exists.

Current tests

No test calls ProgramExit or checks exit-time release of the music track.

Regression test

Either register the call (for example from Game disposal or an atexit handler installed on first Play) and test that the track is released and the state is Stopped, or change the header to say the host must call it.

Blast radius

Games that exit while music is playing; the operating system reclaims the memory, so the practical effect is limited to exit-time ordering and leak reports. C API hosts that call the export are covered.

Workaround

Call MediaPlayer::Stop() (or ProgramExit()) before leaving Run().

The same subject is explained at several altitudes. These are the neighbouring pages at each one.

Known issues
Bug index