Avoid deadlock when closing the progress dialog

Don't call EndDialog() while inside the critical section, this could
(and did, sometimes) result in a deadlock if the main thread was trying
to enter it in order to send us wxSPDD_DESTROYED notification as
EndDialog() needs it to process some messages.
This commit is contained in:
Vadim Zeitlin
2017-10-29 20:31:33 +01:00
parent d7ec02636a
commit 2b8e84ca49

View File

@@ -1103,6 +1103,10 @@ wxProgressDialogTaskRunner::TaskDialogCallbackProc
LONG_PTR dwRefData LONG_PTR dwRefData
) )
{ {
bool endDialog = false;
// Block for shared data critical section.
{
wxProgressDialogSharedData * const sharedData = wxProgressDialogSharedData * const sharedData =
(wxProgressDialogSharedData *) dwRefData; (wxProgressDialogSharedData *) dwRefData;
@@ -1230,13 +1234,28 @@ wxProgressDialogTaskRunner::TaskDialogCallbackProc
(sharedData->m_state == wxProgressDialog::Finished && (sharedData->m_state == wxProgressDialog::Finished &&
sharedData->m_style & wxPD_AUTO_HIDE) ) sharedData->m_style & wxPD_AUTO_HIDE) )
{ {
::EndDialog( hwnd, IDCLOSE ); // Don't call EndDialog() from here as it could deadlock
// because we are inside the shared data critical section, do
// it below after leaving it instead.
endDialog = true;
} }
sharedData->m_notifications = 0; sharedData->m_notifications = 0;
if ( endDialog )
break;
return S_FALSE; return S_FALSE;
} }
} // Leave shared data critical section.
if ( endDialog )
{
::EndDialog( hwnd, IDCLOSE );
return S_FALSE;
}
// Return anything. // Return anything.
return S_OK; return S_OK;
} }