am 2925b8c6: Merge change 25496 into eclair
Merge commit '2925b8c62a03381e5b3ff159847e8312ae9dfee5' into eclair-plus-aosp * commit '2925b8c62a03381e5b3ff159847e8312ae9dfee5': Fix issue 2127371: Possible race condition in AudioFlinger::openRecord() when a Track is being destroyed.
This commit is contained in:
@@ -307,6 +307,9 @@ sp<IAudioTrack> AudioFlinger::createTrack(
|
|||||||
if (lStatus == NO_ERROR) {
|
if (lStatus == NO_ERROR) {
|
||||||
trackHandle = new TrackHandle(track);
|
trackHandle = new TrackHandle(track);
|
||||||
} else {
|
} 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();
|
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());
|
LOGV("removeClient_l() pid %d, tid %d, calling tid %d", pid, gettid(), IPCThreadState::self()->getCallingPid());
|
||||||
Mutex::Autolock _l(mLock);
|
|
||||||
mClients.removeItem(pid);
|
mClients.removeItem(pid);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2078,8 +2081,11 @@ AudioFlinger::ThreadBase::TrackBase::~TrackBase()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
mCblkMemory.clear(); // and free the shared memory
|
mCblkMemory.clear(); // and free the shared memory
|
||||||
|
if (mClient != NULL) {
|
||||||
|
Mutex::Autolock _l(mClient->audioFlinger()->mLock);
|
||||||
mClient.clear();
|
mClient.clear();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void AudioFlinger::ThreadBase::TrackBase::releaseBuffer(AudioBufferProvider::Buffer* buffer)
|
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
|
// 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()
|
AudioFlinger::Client::~Client()
|
||||||
{
|
{
|
||||||
mAudioFlinger->removeClient(mPid);
|
mAudioFlinger->removeClient_l(mPid);
|
||||||
}
|
}
|
||||||
|
|
||||||
const sp<MemoryDealer>& AudioFlinger::Client::heap() const
|
const sp<MemoryDealer>& AudioFlinger::Client::heap() const
|
||||||
@@ -2820,6 +2827,9 @@ sp<IAudioRecord> AudioFlinger::openRecord(
|
|||||||
format, channelCount, frameCount, flags);
|
format, channelCount, frameCount, flags);
|
||||||
}
|
}
|
||||||
if (recordTrack->getCblk() == NULL) {
|
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();
|
recordTrack.clear();
|
||||||
lStatus = NO_MEMORY;
|
lStatus = NO_MEMORY;
|
||||||
goto Exit;
|
goto Exit;
|
||||||
|
|||||||
@@ -189,6 +189,8 @@ private:
|
|||||||
virtual ~Client();
|
virtual ~Client();
|
||||||
const sp<MemoryDealer>& heap() const;
|
const sp<MemoryDealer>& heap() const;
|
||||||
pid_t pid() const { return mPid; }
|
pid_t pid() const { return mPid; }
|
||||||
|
sp<AudioFlinger> audioFlinger() { return mAudioFlinger; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Client(const Client&);
|
Client(const Client&);
|
||||||
Client& operator = (const Client&);
|
Client& operator = (const Client&);
|
||||||
@@ -641,7 +643,7 @@ private:
|
|||||||
friend class PlaybackThread::Track;
|
friend class PlaybackThread::Track;
|
||||||
|
|
||||||
|
|
||||||
void removeClient(pid_t pid);
|
void removeClient_l(pid_t pid);
|
||||||
|
|
||||||
|
|
||||||
// record thread
|
// record thread
|
||||||
|
|||||||
Reference in New Issue
Block a user