From 9535dce82c77679a230aa01cd58c699256e1da13 Mon Sep 17 00:00:00 2001 From: Paul Licameli Date: Mon, 16 May 2016 20:54:46 -0400 Subject: [PATCH] Fix deadlocks in scrubbing, again, and better... see eac6f98cbf97d9cdb240da978581ce21ec0d6f9c --- src/AudioIO.cpp | 21 ++++++++------------- 1 file changed, 8 insertions(+), 13 deletions(-) diff --git a/src/AudioIO.cpp b/src/AudioIO.cpp index 4ece76a9a..e04f13db4 100644 --- a/src/AudioIO.cpp +++ b/src/AudioIO.cpp @@ -415,21 +415,12 @@ struct AudioIO::ScrubQueue void Nudge() { wxMutexLocker locker(mUpdating); - mAvailable.Signal(); - } - - void PoisonPill() - { - // Main thread is shutting down the scrubbing - wxMutexLocker locker(mUpdating); - mPoisoned = true; + mNudged = true; mAvailable.Signal(); } bool Producer(double end, double maxSpeed, bool bySpeed, bool maySkip) { - wxASSERT(!mPoisoned); - // Main thread indicates a scrubbing interval // MAY ADVANCE mLeadingIdx, BUT IT NEVER CATCHES UP TO mTrailingIdx. @@ -471,9 +462,11 @@ struct AudioIO::ScrubQueue // MAY ADVANCE mMiddleIdx, WHICH MAY EQUAL mLeadingIdx, BUT DOES NOT PASS IT. wxMutexLocker locker(mUpdating); - while(!mPoisoned && mMiddleIdx == mLeadingIdx) + while(!mNudged && mMiddleIdx == mLeadingIdx) mAvailable.Wait(); + mNudged = false; + if (mMiddleIdx != mLeadingIdx) { // There is work in the queue @@ -703,7 +696,7 @@ private: wxLongLong mLastScrubTimeMillis; mutable wxMutex mUpdating; mutable wxCondition mAvailable { mUpdating }; - bool mPoisoned { false }; + bool mNudged { false }; }; #endif @@ -2199,7 +2192,7 @@ void AudioIO::StopStream() mAudioThreadFillBuffersLoopRunning = false; if (mScrubQueue) - mScrubQueue->PoisonPill(); + mScrubQueue->Nudge(); // Audacity can deadlock if it tries to update meters while // we're stopping PortAudio (because the meter updating code @@ -2303,6 +2296,8 @@ void AudioIO::StopStream() // PRL: Made it safe yield to avoid a certain recursive event processing in the // time ruler when switching from scrub to quick play. wxGetApp().SafeYield(nullptr, true); // Pass true for onlyIfNeeded to avoid recursive call error. + if (mScrubQueue) + mScrubQueue->Nudge(); wxMilliSleep( 50 ); }