OSDN Git Service

audioflinger: Fix for a deadlock in track creation
authorHaynes Mathew George <hgeorge@codeaurora.org>
Fri, 13 Dec 2013 23:40:13 +0000 (15:40 -0800)
committerGlenn Kasten <gkasten@android.com>
Thu, 6 Mar 2014 18:44:13 +0000 (10:44 -0800)
AudioFlinger enters a deadlock (with itself) on trying to free a
RecordTrack or Track object that failed initialization. Clear this
bad object from the caller instead.

Bug: 12423233
Change-Id: I926f2beb922a70f6924e593e2bbf1a5b5df85b16

services/audioflinger/AudioFlinger.cpp
services/audioflinger/Threads.cpp

index e9c38e3..26dac95 100644 (file)
@@ -513,6 +513,8 @@ sp<IAudioTrack> AudioFlinger::createTrack(
 
         track = thread->createTrack_l(client, streamType, sampleRate, format,
                 channelMask, frameCount, sharedBuffer, lSessionId, flags, tid, clientUid, &lStatus);
+        LOG_ALWAYS_FATAL_IF((lStatus == NO_ERROR) && (track == 0));
+        // we don't abort yet if lStatus != NO_ERROR; there is still work to be done regardless
 
         // move effect chain to this output thread if an effect on same session was waiting
         // for a track to be created
@@ -1291,7 +1293,7 @@ sp<IAudioRecord> AudioFlinger::openRecord(
                                                   frameCount, lSessionId,
                                                   IPCThreadState::self()->getCallingUid(),
                                                   flags, tid, &lStatus);
-        LOG_ALWAYS_FATAL_IF((recordTrack != 0) != (lStatus == NO_ERROR));
+        LOG_ALWAYS_FATAL_IF((lStatus == NO_ERROR) && (recordTrack == 0));
     }
     if (lStatus != NO_ERROR) {
         // remove local strong reference to Client before deleting the RecordTrack so that the
index 498ddb6..1da5147 100644 (file)
@@ -1326,6 +1326,7 @@ sp<AudioFlinger::PlaybackThread::Track> AudioFlinger::PlaybackThread::createTrac
         }
         if (track == 0 || track->getCblk() == NULL || track->name() < 0) {
             lStatus = NO_MEMORY;
+            // track must be cleared from the caller as the caller has the AF lock
             goto Exit;
         }
 
@@ -4741,7 +4742,7 @@ sp<AudioFlinger::RecordThread::RecordTrack>  AudioFlinger::RecordThread::createR
         if (track->getCblk() == 0) {
             ALOGE("createRecordTrack_l() no control block");
             lStatus = NO_MEMORY;
-            track.clear();
+            // track must be cleared from the caller as the caller has the AF lock
             goto Exit;
         }
         mTracks.add(track);