Possible issue with DialogWindow::showModalDialog


#1

I tried calling DialogWindow::showModalDialog from another thread than the message thread on Mac OS X and I hit the

CHECK_MESSAGE_MANAGER_IS_LOCKED assert in Component::addToDesktop.

I have hit this assert before, so I add a MessageManagerLock before calling showModalDialog.

Now I hit the assert jassert(! currentThreadHasLockedMessageManager()) in MessageManager::callFunctionOnMessageThread which is called from Component::runModalLoop.

These two asserts contradict each other, meaning that showModalDialog cannot be called from any other thread than the message thread, even though Component::runModalLoop tries to run it on the messsage thread.

On Windows I hit an assert when setting the title for the window, saying that only the message thread can call this function.

I am unsure whether this issue needs to be fixed or whether an assert checking that the current thread is the message thread just needs to be added to DialogWindow::showModalDialog.

My own work around for this issue is to create a DialogWindow with DialogWindow::LaunchOptions::launchAsync() inside a callFunctionOnMessageThread callback and then just call runModalLoop on this window. Example code below.

[code]DialogWindow* window = static_cast<DialogWindow*>( MessageManager::getInstance()->callFunctionOnMessageThread(&CreateDialogWindow, &options) );

window->runModalLoop();[/code]

I could be that this is just the proper way to handle this case or maybe this is an issue which needs to be fixed.


#2

It’s impossible to run a modal loop on any thread except the message thread… If you think about it, it’d make no sense at all to do that.


#3

I understand you cannot run a modal loop from any other thread than the message thread, but you can trigger it from another thread.

This is at least how I understand the following code.

[code]int Component::runModalLoop()
{
if (! MessageManager::getInstance()->isThisTheMessageThread())
{
// use a callback so this can be called from non-gui threads
return (int) (pointer_sized_int) MessageManager::getInstance()
->callFunctionOnMessageThread (&ComponentHelpers::runModalLoopCallback, this);
}

if (! isCurrentlyModal())
    enterModalState (true);

return ModalComponentManager::getInstance()->runEventLoopForCurrentComponent();

}[/code]

What is the point of the callback if its not suppose be called from any other thread than the message thread?


#4

Ah, I forgot that I’d added that!

(It’s very old code, and I actually wouldn’t generally recommend using it, TBH, because it could lead to deadlocks if the message thread tries to stop the thread that’s calling runLoop)


#5

I see.

Are you then also recommending not to use the following functions from other threads the message thread?

AlertWindow::showMessageBox AlertWindow::showMessageBoxAsync AlertWindow::showOkCancelBox AlertWindow::showYesNoCancelBox

Because if you are not using native alert windows, these functions eventually call AlertWindowInfo::invoke which uses callFunctionOnMessageThread and Component::runModalLoop. But you never get any indication that this is a bad idea, as it just works.


#6

Yes, I’d certainly recommend not letting any other thread ever block while waiting for the message thread, because that runs the risk of a deadlock.