diff options
author | Eric Laurent <elaurent@google.com> | 2014-06-08 14:14:17 -0700 |
---|---|---|
committer | Eric Laurent <elaurent@google.com> | 2014-06-08 14:16:32 -0700 |
commit | 59a8923027d2d6a155c0fa434ae65559318da4b6 (patch) | |
tree | abab0761e566b204ef399689ef6e1bd5004357b4 /services | |
parent | 7e45ef9db7446d33c941961c14555413641e444b (diff) | |
download | frameworks_av-59a8923027d2d6a155c0fa434ae65559318da4b6.zip frameworks_av-59a8923027d2d6a155c0fa434ae65559318da4b6.tar.gz frameworks_av-59a8923027d2d6a155c0fa434ae65559318da4b6.tar.bz2 |
audio policy service: fix potential deadlock in destructor
In the AudioCommandThread loop, release mLock before releasing
the strong reference on the service as AudioPolicyService destructor
calls AudioCommandThread::exit() which acquires mLock.
Also check exiPending in thread loop before processing pending
commands or sleeping.
Bug: 15449050.
Change-Id: I148bf21bd67ef721b5b5ee2c1a6afb185c59daa3
Diffstat (limited to 'services')
-rw-r--r-- | services/audiopolicy/AudioPolicyService.cpp | 24 |
1 files changed, 16 insertions, 8 deletions
diff --git a/services/audiopolicy/AudioPolicyService.cpp b/services/audiopolicy/AudioPolicyService.cpp index a2a0461..e86f4a2 100644 --- a/services/audiopolicy/AudioPolicyService.cpp +++ b/services/audiopolicy/AudioPolicyService.cpp @@ -399,7 +399,8 @@ bool AudioPolicyService::AudioCommandThread::threadLoop() mLock.lock(); while (!exitPending()) { - while (!mAudioCommands.isEmpty()) { + sp<AudioPolicyService> svc; + while (!mAudioCommands.isEmpty() && !exitPending()) { nsecs_t curTime = systemTime(); // commands are sorted by increasing time stamp: execute them from index 0 and up if (mAudioCommands[0]->mTime <= curTime) { @@ -452,7 +453,7 @@ bool AudioPolicyService::AudioCommandThread::threadLoop() StopOutputData *data = (StopOutputData *)command->mParam.get(); ALOGV("AudioCommandThread() processing stop output %d", data->mIO); - sp<AudioPolicyService> svc = mService.promote(); + svc = mService.promote(); if (svc == 0) { break; } @@ -464,7 +465,7 @@ bool AudioPolicyService::AudioCommandThread::threadLoop() ReleaseOutputData *data = (ReleaseOutputData *)command->mParam.get(); ALOGV("AudioCommandThread() processing release output %d", data->mIO); - sp<AudioPolicyService> svc = mService.promote(); + svc = mService.promote(); if (svc == 0) { break; } @@ -494,7 +495,7 @@ bool AudioPolicyService::AudioCommandThread::threadLoop() } break; case UPDATE_AUDIOPORT_LIST: { ALOGV("AudioCommandThread() processing update audio port list"); - sp<AudioPolicyService> svc = mService.promote(); + svc = mService.promote(); if (svc == 0) { break; } @@ -504,7 +505,7 @@ bool AudioPolicyService::AudioCommandThread::threadLoop() }break; case UPDATE_AUDIOPATCH_LIST: { ALOGV("AudioCommandThread() processing update audio patch list"); - sp<AudioPolicyService> svc = mService.promote(); + svc = mService.promote(); if (svc == 0) { break; } @@ -542,9 +543,16 @@ bool AudioPolicyService::AudioCommandThread::threadLoop() if (mAudioCommands.isEmpty()) { release_wake_lock(mName.string()); } - ALOGV("AudioCommandThread() going to sleep"); - mWaitWorkCV.waitRelative(mLock, waitTime); - ALOGV("AudioCommandThread() waking up"); + // release mLock before releasing strong reference on the service as + // AudioPolicyService destructor calls AudioCommandThread::exit() which acquires mLock. + mLock.unlock(); + svc.clear(); + mLock.lock(); + if (!exitPending()) { + ALOGV("AudioCommandThread() going to sleep"); + mWaitWorkCV.waitRelative(mLock, waitTime); + ALOGV("AudioCommandThread() waking up"); + } } mLock.unlock(); return false; |