From d7ec02636a1f5c5afa371b8643a06b48674dba2a Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Sun, 29 Oct 2017 20:20:30 +0100 Subject: [PATCH] Avoid spurious assert when cancelling wxProgressDialog If Cancel/close button was pressed twice in a row, assert checking that the dialog state was "Continue" could be triggered, which was worse than annoying as it resulted in a deadlock due to trying to show the assert dialog box while holding the critical section that prevented the main thread from continuing. Allow the state to be either "Continue" or already be set to "Canceled" now to account for this case. Still assert for the other invalid states, but they really aren't supposed to be possible here. --- src/msw/progdlg.cpp | 40 ++++++++++++++++++++++++++++++---------- 1 file changed, 30 insertions(+), 10 deletions(-) diff --git a/src/msw/progdlg.cpp b/src/msw/progdlg.cpp index 2cf0fac97b..ce08c960c6 100644 --- a/src/msw/progdlg.cpp +++ b/src/msw/progdlg.cpp @@ -1175,18 +1175,38 @@ wxProgressDialogTaskRunner::TaskDialogCallbackProc // a finished dialog. if ( sharedData->m_style & wxPD_CAN_ABORT ) { - wxCHECK_MSG - ( - sharedData->m_state == wxProgressDialog::Continue, - TRUE, - "Dialog not in a cancelable state!" - ); + switch ( sharedData->m_state ) + { + case wxProgressDialog::Canceled: + // It can happen that we receive a second + // cancel request before we had time to process + // the first one, in which case simply do + // nothing for the subsequent one. + break; - ::SendMessage(hwnd, TDM_ENABLE_BUTTON, Id_SkipBtn, FALSE); - EnableCloseButtons(hwnd, false); + case wxProgressDialog::Continue: + ::SendMessage(hwnd, TDM_ENABLE_BUTTON, Id_SkipBtn, FALSE); + EnableCloseButtons(hwnd, false); - sharedData->m_timeStop = wxGetCurrentTime(); - sharedData->m_state = wxProgressDialog::Canceled; + sharedData->m_timeStop = wxGetCurrentTime(); + sharedData->m_state = wxProgressDialog::Canceled; + break; + + // States which shouldn't be possible here: + + // We shouldn't have an (enabled) cancel button at + // all then. + case wxProgressDialog::Uncancelable: + + // This one was already dealt with above. + case wxProgressDialog::Finished: + + // Normally it shouldn't be possible to get any + // notifications after switching to this state. + case wxProgressDialog::Dismissed: + wxFAIL_MSG( "unreachable" ); + break; + } } return S_FALSE;