CNA-BUG-213: audio.h and AUDIO.md call cna_dynamic_sound_effect_instance_submit_buffer safe from a producer thread, but every call off the creation thread returns CNA_RESULT_THREAD

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.

The submission routes resolve the instance through HandleRegistry::Get, which refuses any thread other than the handle's creation thread, so the documented canonical producer-thread usage fails; AUDIO.md's own threading section states the stricter rule.

Identifier
CNA-BUG-213
Category
Bug
Subsystem
C API & bindings
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_dynamic_sound_effect_instance_submit_buffer, cna_dynamic_sound_effect_instance_submit_float_buffer_ext

Expected behaviour

The Doxygen of cna_dynamic_sound_effect_instance_submit_buffer in audio.h says copying the bytes “is what makes this route safe to call from a producer thread while playback runs, which is the canonical usage”; AUDIO.md repeats it for streaming instances.

Actual behaviour at TARGET

Both routes in CnaCApiAudio.cpp call BorrowDynamicInstance → GetSoundEffectInstance → HandleRegistry::Get, and Get in CnaCApiDetail.hpp returns CNA_RESULT_THREAD whenever the calling thread is not the slot's creation thread. AUDIO.md's “Threads, hardware and shutdown” section says every audio call runs on the game creation thread, so the documents contradict each other and the code follows the stricter statement.

Source locations

Evidence

Checked by reading at 009d40f5; not executed.

Focused reproduction

/* Illustrative C; not compiled. 'instance' was created on the game thread. */
static int producer(void* arg) {
    CNA_Handle instance = *(CNA_Handle*)arg;
    uint8_t pcm[4096] = {0};
    return (int)cna_dynamic_sound_effect_instance_submit_buffer(instance, pcm, sizeof pcm, 0, 4096);
}
/* Expected by audio.h: CNA_RESULT_SUCCESS. Actual by reading: CNA_RESULT_THREAD. */

Current tests

AudioStreamingSmoke.c submits from the creation thread only.

Regression test

A pure-C test that submits from a second thread and asserts whichever contract is chosen; then align audio.h and AUDIO.md (or relax the thread check for these two routes, if the native instance is safe for it).

Blast radius

C and binding code that follows the header and feeds a streaming instance from an audio producer thread. Single-threaded submission is unaffected.

Workaround

Marshal submissions to the game creation thread.

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

User guide
C API: limits
Known issues
Bug index