From 0c4514efb0788e5f19913802e1aa011cfcc24321 Mon Sep 17 00:00:00 2001 From: Paul Licameli Date: Wed, 26 Aug 2020 16:01:54 -0400 Subject: [PATCH] Avoid some unexpected recursions because of yields to event loop... ... See code comments. Not proved to be a cause of data loss bugs, but they caused surprises when trying to step in the debugger. --- src/ProjectAudioManager.cpp | 13 +++++++++---- src/SqliteSampleBlock.cpp | 9 +++++++++ 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/src/ProjectAudioManager.cpp b/src/ProjectAudioManager.cpp index a4cb83fca..148e4db5a 100644 --- a/src/ProjectAudioManager.cpp +++ b/src/ProjectAudioManager.cpp @@ -910,16 +910,21 @@ void ProjectAudioManager::OnAudioIOStopRecording() history.ModifyState( true ); // this might fail and throw - ShowWarningDialog(&window, wxT("DropoutDetected"), XO("\ + // CallAfter so that we avoid any problems of yielding + // to the event loop while still inside the timer callback, + // entering StopStream() recursively + wxTheApp->CallAfter( [&] { + ShowWarningDialog(&window, wxT("DropoutDetected"), XO("\ Recorded audio was lost at the labeled locations. Possible causes:\n\ \n\ Other applications are competing with Audacity for processor time\n\ \n\ You are saving directly to a slow external storage device\n\ " - ), - false, - XXO("Turn off dropout detection")); + ), + false, + XXO("Turn off dropout detection")); + }); } } } diff --git a/src/SqliteSampleBlock.cpp b/src/SqliteSampleBlock.cpp index 589d7df51..39e51df55 100644 --- a/src/SqliteSampleBlock.cpp +++ b/src/SqliteSampleBlock.cpp @@ -268,6 +268,15 @@ SqliteSampleBlock::SqliteSampleBlock( SqliteSampleBlock::~SqliteSampleBlock() { + if (mBlockID == 0) { + // The block object was constructed but failed to Load() or Commit(). + // Just let the stack unwind. Don't violate the assertion in + // Delete(), which may do odd recursive things in debug builds when it + // yields to the UI to put up a dialog, but then dispatches timer + // events that try again to finish recording. + return; + } + // See ProjectFileIO::Bypass() for a description of mIO.mBypass if (!mLocked && !Conn()->ShouldBypass()) {