Some more info I just excavated from the crash dump: when the crash happens in an XAudio CGraphManager thread, the main thread is somewhere deep in XACT::CCue::Destroy, waiting in CGraphManager::WaitForThread(). Could this be a multithreading issue where the graph manager thread tries to access data which has already been free'd by the main thread?
Here's the call stack of the main thread:
XAudio2_1.dll!_XLFQueueAdd@8() + 0xa7 Bytes
XAudio2_1.dll!CGraphManager::WaitForThread() + 0x2d Bytes
XAudio2_1.dll!CLeapSystem::WaitForGraph() + 0x10 Bytes
XAudio2_1.dll!CX2SourceVoice::Destroy() + 0x82 Bytes
XAudio2_1.dll!CX2SourceVoiceWMA::~CX2SourceVoiceWMA() + 0x33 Bytes
XAudio2_1.dll!CX2SourceVoiceWMA::`scalar deleting destructor'() + 0x11 Bytes
XAudio2_1.dll!CMemoryHelper::Delete<CX2Voice>() + 0x32 Bytes
XAudio2_1.dll!CX2Voice::InternalDestroyVoice() + 0x2c Bytes
XAudio2_1.dll!CX2Voice::DestroyVoice() + 0x4c Bytes
XAudio2_1.dll!CX2SourceVoice::DestroyVoice() + 0x11 Bytes
xactengine3_1.dll!XACT::CXAudio2SourceVoice::~CXAudio2SourceVoice() + 0x2f Bytes
xactengine3_1.dll!XACT::CXAudio2SourceVoice::`scalar deleting destructor'() + 0x11 Bytes
xactengine3_1.dll!XACT::CXAudio2Renderer::DestroyVoice() + 0x6f Bytes
xactengine3_1.dll!XACT::CWave::Cleanup() + 0xc3 Bytes
xactengine3_1.dll!XACT::CStreamingWave::~CStreamingWave() + 0x3a Bytes
xactengine3_1.dll!XACT::CStreamingWave::`scalar deleting destructor'() + 0x11 Bytes
xactengine3_1.dll!XACT::CEventPlayWave::~CEventPlayWave() + 0x39 Bytes
xactengine3_1.dll!XACT::CEventPlayWave::`scalar deleting destructor'() + 0x11 Bytes
xactengine3_1.dll!XACT::CClip::~CClip() + 0x88 Bytes
xactengine3_1.dll!XACT::CClip::`vector deleting destructor'() + 0x11 Bytes
xactengine3_1.dll!XACT::CTrack::~CTrack() + 0x6a Bytes
xactengine3_1.dll!XACT::CTrack::`scalar deleting destructor'() + 0x11 Bytes
xactengine3_1.dll!XACT::CSound::~CSound() + 0xad Bytes
xactengine3_1.dll!XACT::CComplexSound::~CComplexSound() + 0x24 Bytes
xactengine3_1.dll!XACT::CComplexSound::`vector deleting destructor'() + 0x11 Bytes
xactengine3_1.dll!XACT::CSound::RegistryHostShutdown() + 0x4a Bytes
xactengine3_1.dll!XACT::CCue::~CCue() + 0xf1 Bytes
xactengine3_1.dll!XACT::CComplexCue::~CComplexCue() + 0x42 Bytes
xactengine3_1.dll!XACT::CInteractiveCue::~CInteractiveCue() + 0x12d Bytes
xactengine3_1.dll!XACT::CInteractiveCue::`scalar deleting destructor'() + 0x11 Bytes
xactengine3_1.dll!XACT::CCue::Destroy() + 0x4f Bytes
...and the call stack of the CGraphManager thread where the crash is actually happening (which is a read access from address 0):
XAudio2_1.dll!CX2SourceVoiceWMA::UpdateLeapVoiceQueue() + 0x905 Bytes
XAudio2_1.dll!CX2SourceVoiceWMA::OnVoiceProcessingPassStart() + 0x34 Bytes
XAudio2_1.dll!CSWVoice::Process() + 0x1e4 Bytes
XAudio2_1.dll!CGraphManager::ProcessGraph() + 0xc3 Bytes
XAudio2_1.dll!CGraphManager::ThreadProc() + 0x1b8 Bytes
XAudio2_1.dll!CThreadBase::StaticThreadProc() + 0x38 Bytes
Could this be related to the following known issue:
Don't Flush Source Buffers Immediately Before Destroying a Voice
In the March 2008 and later SDKs, titles should not call IXAudio2SourceVoice::FlushSourceBuffers immediately before calling IXAudio2SourceVoice::DestroyVoice. Titles that do call FlushSourceBuffers immediately before DestroyVoice
may cause the title to crash. Titles that must flush source buffers
before destroying the voice should insert a short pause between
flushing the buffers and destroying the voice. For example, the title
might have code similar to the following:
pSourceVoice->FlushSourceBuffer();
Sleep( 2 );
pSourceVoice->DestroyVoice();
In a future release of the SDK, titles will not need to insert the short pause.
We don't call XAudio directly but do anything through XACT3. In this case we do a
xactCue->Stop(0) followed by xactCue->Destroy()
Should we do this instead:
xactCue->Stop(XACT_FLAG_CUE_STOP_IMMEDIATE); Sleep(2); xactCue->Destroy();
I'll just try that ;)
-Floh.