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()) {