summaryrefslogtreecommitdiffstats
path: root/services
diff options
context:
space:
mode:
authorEric Laurent <elaurent@google.com>2014-06-08 14:14:17 -0700
committerEric Laurent <elaurent@google.com>2014-06-08 14:16:32 -0700
commit59a8923027d2d6a155c0fa434ae65559318da4b6 (patch)
treeabab0761e566b204ef399689ef6e1bd5004357b4 /services
parent7e45ef9db7446d33c941961c14555413641e444b (diff)
downloadframeworks_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.cpp24
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;