On SoundSDL destructor and `reset()`, there was a deadlock with Linux pthreads, it happened sometimes that the reader thread would call `SDL_SemWait(data_available)` while `deinit()` would destroy the semaphore and the `SDL_SemWait()` would end up waiting forever on a null semaphore. Change the sequencing of deinit() to prevent this from happening, set `initialized = false` at the beginning of the sequence to prevent subsequent entries into the reader callback, and add an SDL_Delay(100) between the final `SDL_SemPost()` and `SDL_UnlockMutex()`s and the `SDL_DestroySemaphore()` and `SDL_DestroyMutex()`s to allow a running reader to complete with a valid mutex and semaphores before they are destroyed and the thread is joined. Resetting the sound system also sometimes triggers a memory corruption bug, but that's a separate issue.
This commit is contained in:
parent
3d792457b2
commit
e9a86c541d
|
@ -51,12 +51,13 @@ std::size_t SoundSDL::buffer_size() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void SoundSDL::read(uint16_t* stream, int length) {
|
void SoundSDL::read(uint16_t* stream, int length) {
|
||||||
if (!initialized || length <= 0)
|
if (length <= 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
SDL_memset(stream, audio_spec.silence, length);
|
SDL_memset(stream, audio_spec.silence, length);
|
||||||
|
|
||||||
if (!emulating)
|
// if not initialzed, paused or shutting down, do nothing
|
||||||
|
if (!initialized || !emulating)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (!buffer_size())
|
if (!buffer_size())
|
||||||
|
@ -148,6 +149,8 @@ void SoundSDL::deinit() {
|
||||||
if (!initialized)
|
if (!initialized)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
initialized = false;
|
||||||
|
|
||||||
SDL_LockMutex(mutex);
|
SDL_LockMutex(mutex);
|
||||||
int is_emulating = emulating;
|
int is_emulating = emulating;
|
||||||
emulating = 0;
|
emulating = 0;
|
||||||
|
@ -155,6 +158,8 @@ void SoundSDL::deinit() {
|
||||||
SDL_SemPost(data_read);
|
SDL_SemPost(data_read);
|
||||||
SDL_UnlockMutex(mutex);
|
SDL_UnlockMutex(mutex);
|
||||||
|
|
||||||
|
SDL_Delay(100);
|
||||||
|
|
||||||
SDL_DestroySemaphore(data_available);
|
SDL_DestroySemaphore(data_available);
|
||||||
data_available = nullptr;
|
data_available = nullptr;
|
||||||
SDL_DestroySemaphore(data_read);
|
SDL_DestroySemaphore(data_read);
|
||||||
|
@ -166,8 +171,6 @@ void SoundSDL::deinit() {
|
||||||
SDL_CloseAudioDevice(sound_device);
|
SDL_CloseAudioDevice(sound_device);
|
||||||
|
|
||||||
emulating = is_emulating;
|
emulating = is_emulating;
|
||||||
|
|
||||||
initialized = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SoundSDL::~SoundSDL() {
|
SoundSDL::~SoundSDL() {
|
||||||
|
|
Loading…
Reference in New Issue