1
0
mirror of https://github.com/cookiengineer/audacity synced 2025-06-18 09:00:07 +02:00

Fix deadlocks in scrubbing, again, and better...

This commit is contained in:
Paul Licameli 2016-05-16 23:13:27 -04:00
commit acf16977be

View File

@ -415,21 +415,12 @@ struct AudioIO::ScrubQueue
void Nudge() void Nudge()
{ {
wxMutexLocker locker(mUpdating); wxMutexLocker locker(mUpdating);
mAvailable.Signal(); mNudged = true;
}
void PoisonPill()
{
// Main thread is shutting down the scrubbing
wxMutexLocker locker(mUpdating);
mPoisoned = true;
mAvailable.Signal(); mAvailable.Signal();
} }
bool Producer(double end, double maxSpeed, bool bySpeed, bool maySkip) bool Producer(double end, double maxSpeed, bool bySpeed, bool maySkip)
{ {
wxASSERT(!mPoisoned);
// Main thread indicates a scrubbing interval // Main thread indicates a scrubbing interval
// MAY ADVANCE mLeadingIdx, BUT IT NEVER CATCHES UP TO mTrailingIdx. // 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. // MAY ADVANCE mMiddleIdx, WHICH MAY EQUAL mLeadingIdx, BUT DOES NOT PASS IT.
wxMutexLocker locker(mUpdating); wxMutexLocker locker(mUpdating);
while(!mPoisoned && mMiddleIdx == mLeadingIdx) while(!mNudged && mMiddleIdx == mLeadingIdx)
mAvailable.Wait(); mAvailable.Wait();
mNudged = false;
if (mMiddleIdx != mLeadingIdx) if (mMiddleIdx != mLeadingIdx)
{ {
// There is work in the queue // There is work in the queue
@ -703,7 +696,7 @@ private:
wxLongLong mLastScrubTimeMillis; wxLongLong mLastScrubTimeMillis;
mutable wxMutex mUpdating; mutable wxMutex mUpdating;
mutable wxCondition mAvailable { mUpdating }; mutable wxCondition mAvailable { mUpdating };
bool mPoisoned { false }; bool mNudged { false };
}; };
#endif #endif
@ -2199,7 +2192,7 @@ void AudioIO::StopStream()
mAudioThreadFillBuffersLoopRunning = false; mAudioThreadFillBuffersLoopRunning = false;
if (mScrubQueue) if (mScrubQueue)
mScrubQueue->PoisonPill(); mScrubQueue->Nudge();
// Audacity can deadlock if it tries to update meters while // Audacity can deadlock if it tries to update meters while
// we're stopping PortAudio (because the meter updating code // 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 // PRL: Made it safe yield to avoid a certain recursive event processing in the
// time ruler when switching from scrub to quick play. // time ruler when switching from scrub to quick play.
wxGetApp().SafeYield(nullptr, true); // Pass true for onlyIfNeeded to avoid recursive call error. wxGetApp().SafeYield(nullptr, true); // Pass true for onlyIfNeeded to avoid recursive call error.
if (mScrubQueue)
mScrubQueue->Nudge();
wxMilliSleep( 50 ); wxMilliSleep( 50 );
} }