Fix audio shutdown crashes

This commit is contained in:
elasota
2020-01-18 18:39:54 -05:00
parent c79ddd0d35
commit 69ef542969
3 changed files with 24 additions and 4 deletions

View File

@@ -55,11 +55,14 @@ namespace PortabilityLayer
enum WorkingState
{
// NOTE: In all cases where the thread event is fired, the event may be fired under a mutex lock.
// Therefore, if the mutex is to be destroyed, it must be locked first even though the thread has transitioned to idle.
State_Idle, // No thread is playing sound, the sound thread is out of work
State_PlayingAsync, // Sound thread is playing sound. When it finishes, it will digest queue events under a lock.
State_PlayingBlocked, // Sound thread is playing sound. When it finishes, it will transition to Idle and fire the thread event.
State_FlushStarting, // Sound thread is aborting. When it aborts, it will transition to Idle and fire the thread event.
State_ShuttingDown, // Sound thread is shutting down. When it finishes, it will transition to idle and fire the thread event.
State_ShuttingDown, // Sound thread is shutting down. When it finishes, it will transition to Idle and fire the thread event.
};
static const unsigned int kMaxQueuedCommands = 64;
@@ -97,6 +100,7 @@ namespace PortabilityLayer
{
m_mutex->Destroy();
m_threadEvent->Destroy();
m_audioChannel->Destroy();
}
void AudioChannelImpl::NotifyBufferFinished()
@@ -121,8 +125,13 @@ namespace PortabilityLayer
{
ClearAllCommands();
bool synchronizeMutex = false;
if (!wait)
{
Stop();
synchronizeMutex = true;
}
else
{
m_mutex->Lock();
@@ -133,6 +142,8 @@ namespace PortabilityLayer
m_mutex->Unlock();
m_threadEvent->Wait();
synchronizeMutex = true;
}
else
{
@@ -141,6 +152,15 @@ namespace PortabilityLayer
}
}
if (synchronizeMutex)
{
// If we had to stop the audio thread, then the event was fired under a lock.
// We have to wait for the unlock to complete before destroying the mutex.
m_mutex->Lock();
assert(m_state == State_Idle);
m_mutex->Unlock();
}
this->~AudioChannelImpl();
PortabilityLayer::MemoryManager::GetInstance()->Release(this);
}