summaryrefslogtreecommitdiffstats
path: root/libs
diff options
context:
space:
mode:
authorAndroid (Google) Code Review <android-gerrit@google.com>2009-09-18 02:55:00 -0400
committerAndroid (Google) Code Review <android-gerrit@google.com>2009-09-18 02:55:00 -0400
commit2925b8c62a03381e5b3ff159847e8312ae9dfee5 (patch)
tree8897f49792ada5363176047cc10de96579a288d0 /libs
parent56af9e9f9cbc3626acf55558d581efd2de3caa03 (diff)
parentb9481d8cf6f3ade96ed062dc3f601c777fe4430f (diff)
downloadframeworks_base-2925b8c62a03381e5b3ff159847e8312ae9dfee5.zip
frameworks_base-2925b8c62a03381e5b3ff159847e8312ae9dfee5.tar.gz
frameworks_base-2925b8c62a03381e5b3ff159847e8312ae9dfee5.tar.bz2
Merge change 25496 into eclair
* changes: Fix issue 2127371: Possible race condition in AudioFlinger::openRecord() when a Track is being destroyed.
Diffstat (limited to 'libs')
-rw-r--r--libs/audioflinger/AudioFlinger.cpp20
-rw-r--r--libs/audioflinger/AudioFlinger.h4
2 files changed, 18 insertions, 6 deletions
diff --git a/libs/audioflinger/AudioFlinger.cpp b/libs/audioflinger/AudioFlinger.cpp
index add358b..e534447 100644
--- a/libs/audioflinger/AudioFlinger.cpp
+++ b/libs/audioflinger/AudioFlinger.cpp
@@ -307,6 +307,9 @@ sp<IAudioTrack> AudioFlinger::createTrack(
if (lStatus == NO_ERROR) {
trackHandle = new TrackHandle(track);
} else {
+ // remove local strong reference to Client before deleting the Track so that the Client
+ // destructor is called by the TrackBase destructor with mLock held
+ client.clear();
track.clear();
}
@@ -707,10 +710,10 @@ void AudioFlinger::audioConfigChanged_l(int event, const sp<ThreadBase>& thread,
}
}
-void AudioFlinger::removeClient(pid_t pid)
+// removeClient_l() must be called with AudioFlinger::mLock held
+void AudioFlinger::removeClient_l(pid_t pid)
{
- LOGV("removeClient() pid %d, tid %d, calling tid %d", pid, gettid(), IPCThreadState::self()->getCallingPid());
- Mutex::Autolock _l(mLock);
+ LOGV("removeClient_l() pid %d, tid %d, calling tid %d", pid, gettid(), IPCThreadState::self()->getCallingPid());
mClients.removeItem(pid);
}
@@ -2078,7 +2081,10 @@ AudioFlinger::ThreadBase::TrackBase::~TrackBase()
}
}
mCblkMemory.clear(); // and free the shared memory
- mClient.clear();
+ if (mClient != NULL) {
+ Mutex::Autolock _l(mClient->audioFlinger()->mLock);
+ mClient.clear();
+ }
}
void AudioFlinger::ThreadBase::TrackBase::releaseBuffer(AudioBufferProvider::Buffer* buffer)
@@ -2712,9 +2718,10 @@ AudioFlinger::Client::Client(const sp<AudioFlinger>& audioFlinger, pid_t pid)
// 1 MB of address space is good for 32 tracks, 8 buffers each, 4 KB/buffer
}
+// Client destructor must be called with AudioFlinger::mLock held
AudioFlinger::Client::~Client()
{
- mAudioFlinger->removeClient(mPid);
+ mAudioFlinger->removeClient_l(mPid);
}
const sp<MemoryDealer>& AudioFlinger::Client::heap() const
@@ -2820,6 +2827,9 @@ sp<IAudioRecord> AudioFlinger::openRecord(
format, channelCount, frameCount, flags);
}
if (recordTrack->getCblk() == NULL) {
+ // remove local strong reference to Client before deleting the RecordTrack so that the Client
+ // destructor is called by the TrackBase destructor with mLock held
+ client.clear();
recordTrack.clear();
lStatus = NO_MEMORY;
goto Exit;
diff --git a/libs/audioflinger/AudioFlinger.h b/libs/audioflinger/AudioFlinger.h
index 7a6641f..3699019 100644
--- a/libs/audioflinger/AudioFlinger.h
+++ b/libs/audioflinger/AudioFlinger.h
@@ -189,6 +189,8 @@ private:
virtual ~Client();
const sp<MemoryDealer>& heap() const;
pid_t pid() const { return mPid; }
+ sp<AudioFlinger> audioFlinger() { return mAudioFlinger; }
+
private:
Client(const Client&);
Client& operator = (const Client&);
@@ -641,7 +643,7 @@ private:
friend class PlaybackThread::Track;
- void removeClient(pid_t pid);
+ void removeClient_l(pid_t pid);
// record thread