Builds with AddressSanitizer enabled fail every time the dunelegacy intro sequence runs to completion when in "Music Type = xmi" mode. (Repro: Do an MSVC build of the xmidi-import branch with the "windows-x64-asan-debug" CMake preset--which shows up as "Windows x64 ASAN Debug" in the VS configuration drop-down, set the "Music Type" to "xmi" and the "Play Intro" to "true" in "Dune Legacy.ini". Then run dunelegacy.exe in the debugger and wait for the intro to complete.)
Here are stack traces showing the SDL audio thread and the worker thread when the break happened.
This is where the debugger breaks the worker thread while it runs MidiProc():
And here here is the audio thread part-way through midiStreamClose():
winmmbase.dll!midiStreamClose()
dunelegacy.exe!native_midi_stop() Line 299
at C:\src\game\dunelegacy\external\SDL_mixer\SDL_mixer\src\codecs\native_midi\native_midi_win32.c(299)
dunelegacy.exe!NATIVEMIDI_Stop(void * context=0x000011cbbf911a80) Line 78
at C:\src\game\dunelegacy\external\SDL_mixer\SDL_mixer\src\codecs\music_nativemidi.c(78)
dunelegacy.exe!music_internal_halt() Line 1153
at C:\src\game\dunelegacy\external\SDL_mixer\SDL_mixer\src\music.c(1153)
dunelegacy.exe!music_mixer(void * udata=0x0000000000000000, unsigned char * stream=0x000011dfbf8c3200, int len=0x00000000) Line 359
at C:\src\game\dunelegacy\external\SDL_mixer\SDL_mixer\src\music.c(359)
dunelegacy.exe!mix_channels(void * udata=0x0000000000000000, unsigned char * stream=0x000011dfbf8c3200, int len=0x00001000) Line 294
at C:\src\game\dunelegacy\external\SDL_mixer\SDL_mixer\src\mixer.c(294)
SDL2d.dll!SDL_RunAudio(void * devicep=0x000011c9bf8efa00) Line 727
at C:\src\game\dunelegacy\external\vcpkg\vcpkg\buildtrees\sdl2\src\e268dc78a1-c01e78abe3.clean\src\audio\SDL_audio.c(727)
SDL2d.dll!SDL_RunThread(SDL_Thread * thread=0x000011c9bf8fab00) Line 275
at C:\src\game\dunelegacy\external\vcpkg\vcpkg\buildtrees\sdl2\src\e268dc78a1-c01e78abe3.clean\src\thread\SDL_thread.c(275)
SDL2d.dll!RunThread(void * data=0x000011c9bf8fab00) Line 83
at C:\src\game\dunelegacy\external\vcpkg\vcpkg\buildtrees\sdl2\src\e268dc78a1-c01e78abe3.clean\src\thread\windows\SDL_systhread.c(83)
SDL2d.dll!RunThreadViaCreateThread(void * data=0x000011c9bf8fab00) Line 93
at C:\src\game\dunelegacy\external\vcpkg\vcpkg\buildtrees\sdl2\src\e268dc78a1-c01e78abe3.clean\src\thread\windows\SDL_systhread.c(93)
clang_rt.asan_dbg_dynamic-x86_64.dll!__asan::AsanThread::ThreadStart(unsigned __int64,struct __sanitizer::atomic_uintptr_t *)
kernel32.dll!BaseThreadInitThunk()
ntdll.dll!RtlUserThreadStart()
I think this is caused by midiOutUnprepareHeader() trying to use the hMidiStream that was just destroyed by the in-progress call to midiStreamClose().
The above traces are from SDL_mixer's main branch (on 1d00166, but it looks pretty much the same with the 2.0.4 release (not much of that code has changed).
When a song ends, there appears to be a race between
native_midi_stop()
's call tomidiStreamClose()
and theMidiProc()
callback triggered by the call tomidiStreamStop()
, which happens on a thread-pool worker thread (at least, it does on Windows 11).Builds with AddressSanitizer enabled fail every time the dunelegacy intro sequence runs to completion when in
"Music Type = xmi"
mode. (Repro: Do an MSVC build of the xmidi-import branch with the "windows-x64-asan-debug" CMake preset--which shows up as "Windows x64 ASAN Debug" in the VS configuration drop-down, set the "Music Type" to "xmi" and the "Play Intro" to "true" in "Dune Legacy.ini". Then run dunelegacy.exe in the debugger and wait for the intro to complete.)Here are stack traces showing the SDL audio thread and the worker thread when the break happened.
This is where the debugger breaks the worker thread while it runs
MidiProc()
:And here here is the audio thread part-way through
midiStreamClose()
:I think this is caused by
midiOutUnprepareHeader()
trying to use thehMidiStream
that was just destroyed by the in-progress call tomidiStreamClose()
.The above traces are from SDL_mixer's main branch (on 1d00166, but it looks pretty much the same with the 2.0.4 release (not much of that code has changed).