Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 735f45fb authored by Glenn Kasten's avatar Glenn Kasten
Browse files

Fix memory access error due to race during fast track removal

Bug: 16205169
Change-Id: Ie15ec2a737b6ddd16b2d26030d01564ff70177f5
parent a7ee3549
Loading
Loading
Loading
Loading
+29 −7
Original line number Original line Diff line number Diff line
@@ -5017,9 +5017,12 @@ reacquire_wakelock:
        // activeTracks accumulates a copy of a subset of mActiveTracks
        // activeTracks accumulates a copy of a subset of mActiveTracks
        Vector< sp<RecordTrack> > activeTracks;
        Vector< sp<RecordTrack> > activeTracks;


        // reference to the (first and only) fast track
        // reference to the (first and only) active fast track
        sp<RecordTrack> fastTrack;
        sp<RecordTrack> fastTrack;


        // reference to a fast track which is about to be removed
        sp<RecordTrack> fastTrackToRemove;

        { // scope for mLock
        { // scope for mLock
            Mutex::Autolock _l(mLock);
            Mutex::Autolock _l(mLock);


@@ -5058,6 +5061,10 @@ reacquire_wakelock:


                activeTrack = mActiveTracks[i];
                activeTrack = mActiveTracks[i];
                if (activeTrack->isTerminated()) {
                if (activeTrack->isTerminated()) {
                    if (activeTrack->isFastTrack()) {
                        ALOG_ASSERT(fastTrackToRemove == 0);
                        fastTrackToRemove = activeTrack;
                    }
                    removeTrack_l(activeTrack);
                    removeTrack_l(activeTrack);
                    mActiveTracks.remove(activeTrack);
                    mActiveTracks.remove(activeTrack);
                    mActiveTracksGen++;
                    mActiveTracksGen++;
@@ -5130,10 +5137,12 @@ reacquire_wakelock:
            effectChains[i]->process_l();
            effectChains[i]->process_l();
        }
        }


        // Start the fast capture if it's not already running
        // Push a new fast capture state if fast capture is not already running, or cblk change
        if (mFastCapture != 0) {
        if (mFastCapture != 0) {
            FastCaptureStateQueue *sq = mFastCapture->sq();
            FastCaptureStateQueue *sq = mFastCapture->sq();
            FastCaptureState *state = sq->begin();
            FastCaptureState *state = sq->begin();
            bool didModify = false;
            FastCaptureStateQueue::block_t block = FastCaptureStateQueue::BLOCK_UNTIL_PUSHED;
            if (state->mCommand != FastCaptureState::READ_WRITE /* FIXME &&
            if (state->mCommand != FastCaptureState::READ_WRITE /* FIXME &&
                    (kUseFastMixer != FastMixer_Dynamic || state->mTrackMask > 1)*/) {
                    (kUseFastMixer != FastMixer_Dynamic || state->mTrackMask > 1)*/) {
                if (state->mCommand == FastCaptureState::COLD_IDLE) {
                if (state->mCommand == FastCaptureState::COLD_IDLE) {
@@ -5147,19 +5156,32 @@ reacquire_wakelock:
                mFastCaptureDumpState.increaseSamplingN(mAudioFlinger->isLowRamDevice() ?
                mFastCaptureDumpState.increaseSamplingN(mAudioFlinger->isLowRamDevice() ?
                        FastCaptureDumpState::kSamplingNforLowRamDevice : FastMixerDumpState::kSamplingN);
                        FastCaptureDumpState::kSamplingNforLowRamDevice : FastMixerDumpState::kSamplingN);
#endif
#endif
                state->mCblk = fastTrack != 0 ? fastTrack->cblk() : NULL;
                didModify = true;
                sq->end();
            }
                sq->push(FastCaptureStateQueue::BLOCK_UNTIL_PUSHED);
            audio_track_cblk_t *cblkOld = state->mCblk;
            audio_track_cblk_t *cblkNew = fastTrack != 0 ? fastTrack->cblk() : NULL;
            if (cblkNew != cblkOld) {
                state->mCblk = cblkNew;
                // block until acked if removing a fast track
                if (cblkOld != NULL) {
                    block = FastCaptureStateQueue::BLOCK_UNTIL_ACKED;
                }
                didModify = true;
            }
            sq->end(didModify);
            if (didModify) {
                sq->push(block);
#if 0
#if 0
                if (kUseFastCapture == FastCapture_Dynamic) {
                if (kUseFastCapture == FastCapture_Dynamic) {
                    mNormalSource = mPipeSource;
                    mNormalSource = mPipeSource;
                }
                }
#endif
#endif
            } else {
                sq->end(false /*didModify*/);
            }
            }
        }
        }


        // now run the fast track destructor with thread mutex unlocked
        fastTrackToRemove.clear();

        // Read from HAL to keep up with fastest client if multiple active tracks, not slowest one.
        // Read from HAL to keep up with fastest client if multiple active tracks, not slowest one.
        // Only the client(s) that are too slow will overrun. But if even the fastest client is too
        // Only the client(s) that are too slow will overrun. But if even the fastest client is too
        // slow, then this RecordThread will overrun by not calling HAL read often enough.
        // slow, then this RecordThread will overrun by not calling HAL read often enough.