InternalMessageQueue::dispatchOverflowMessages() can cause deadlocks

InternalMessageQueue::dispatchOverflowMessages() was introduced to handle situation where JUCE sends too many messages for the Windows message queue to buffer. This happens in our case if Nexus 3 is opened multiple times at once for instance if a user loads a bigger project into a DAW.

Since the overflowQueue needs to be thread safe it locks access with a CriticalSection. However the queue is still locked while the handler of a message itself is called. This can lead to deadlocks if the handling of the message takes some time and within new messages are send. All this while other threads are still trying to send new messages.

Here is an alternative implementation of InternalMessageQueue::dispatchOverflowMessages() that does lock the access to the queue but leaves the queue unlocked while the message handler is called. Since only dispatchOverflowMessages() removes messages from the queue it should be safe to allow other threads to add new messages in between.

	void dispatchOverflowMessages ()
	{
		lock.enter ();

		for ( int i = 0; i < overflowQueue.size (); ++i )
		{
			auto message = overflowQueue.getUnchecked ( i );
			message->incReferenceCount ();

			lock.exit ();
			dispatchMessageFromLParam ( (LPARAM)message.get () );
			lock.enter ();
		}

		overflowQueue.clear ();
		lock.exit ();
	}

Can we get this change done to the official repository on short notice? Otherwise we would need to fork again which we would really like to avoid.

2 Likes

Thanks for the report, I’ve pushed a fix for this in c46194d which should sort things out.