diff --git a/src/AudioIO.cpp b/src/AudioIO.cpp index b8e365981..6ce02ca2d 100644 --- a/src/AudioIO.cpp +++ b/src/AudioIO.cpp @@ -983,7 +983,10 @@ AudioIO::~AudioIO() /* Delete is a "graceful" way to stop the thread. (Kill is the not-graceful way.) */ - wxTheApp->Yield(); + + // This causes reentrancy issues during application shutdown + // wxTheApp->Yield(); + mThread->Delete(); if(mSilentBuf) diff --git a/src/Project.cpp b/src/Project.cpp index 5c0739f57..c6755a74e 100644 --- a/src/Project.cpp +++ b/src/Project.cpp @@ -2070,6 +2070,17 @@ void AudacityProject::OnMouseEvent(wxMouseEvent & event) // and/or attempts to delete objects twice. void AudacityProject::OnCloseWindow(wxCloseEvent & event) { + // We are called for the wxEVT_CLOSE_WINDOW, wxEVT_END_SESSION, and + // wxEVT_QUERY_END_SESSION, so we have to protect against multiple + // entries. This is a hack until the whole application termination + // process can be reviewed and reworked. (See bug #964 for ways + // to exercise the bug that instigated this hack.) + if (mIsBeingDeleted) + { + evt.Skip(); + return; + } + if (event.CanVeto() && (::wxIsBusy() || mbBusyImporting)) { event.Veto(); @@ -2259,10 +2270,10 @@ void AudacityProject::OnCloseWindow(wxCloseEvent & event) if (gActiveProject == this) { // Find a new active project if (gAudacityProjects.Count() > 0) { - gActiveProject = gAudacityProjects[0]; + SetActiveProject(gAudacityProjects[0]); } else { - gActiveProject = NULL; + SetActiveProject(NULL); } } @@ -2286,6 +2297,8 @@ void AudacityProject::OnCloseWindow(wxCloseEvent & event) } Destroy(); + + mIsBeingDeleted = true; } void AudacityProject::OnOpenAudioFile(wxCommandEvent & event) diff --git a/src/Project.h b/src/Project.h index 144d5975f..7a212eacd 100644 --- a/src/Project.h +++ b/src/Project.h @@ -671,6 +671,9 @@ class AUDACITY_DLL_API AudacityProject: public wxFrame, wxLongLong mLastSelectionAdjustment; + // See explanation in OnCloseWindow + bool mIsBeingDeleted; + // CommandManager needs to use private methods friend class CommandManager;