From 5c138561bb08dffd3353c97c8720b4123e524f8a Mon Sep 17 00:00:00 2001 From: reuk Date: Mon, 2 Dec 2024 19:14:15 +0000 Subject: [PATCH] MidiDeviceListConnectionBroadcaster: Avoid constructing MessageManager on incorrect thread Previously, if the very first call to MidiDeviceListConnectionBroadcaster::get() happened on a background thread (which could happen on macOS in response to a MIDI setup configuration change), then MessageManager::getInstance and getAvailableDevices could be called on that same thread. With this change in place, midi change notifications will be ignored if there's no message manager available, and getAvailableDevices will only be called on the message thread. --- ...ce_MidiDeviceListConnectionBroadcaster.cpp | 22 ++++++++++--------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/modules/juce_audio_devices/midi_io/juce_MidiDeviceListConnectionBroadcaster.cpp b/modules/juce_audio_devices/midi_io/juce_MidiDeviceListConnectionBroadcaster.cpp index 89e843d765..c80d2168de 100644 --- a/modules/juce_audio_devices/midi_io/juce_MidiDeviceListConnectionBroadcaster.cpp +++ b/modules/juce_audio_devices/midi_io/juce_MidiDeviceListConnectionBroadcaster.cpp @@ -57,20 +57,22 @@ public: void notify() { - if (MessageManager::getInstance()->isThisTheMessageThread()) - { - cancelPendingUpdate(); + auto* mm = MessageManager::getInstanceWithoutCreating(); - const State newState; + if (mm == nullptr) + return; - if (std::exchange (lastNotifiedState, newState) != newState) - for (auto it = callbacks.begin(); it != callbacks.end();) - NullCheckedInvocation::invoke ((it++)->second); - } - else + if (! mm->isThisTheMessageThread()) { triggerAsyncUpdate(); + return; } + + cancelPendingUpdate(); + + if (auto prev = std::exchange (lastNotifiedState, State{}); prev != lastNotifiedState) + for (auto it = callbacks.begin(); it != callbacks.end();) + NullCheckedInvocation::invoke ((it++)->second); } static auto& get() @@ -108,7 +110,7 @@ private: } std::map> callbacks; - State lastNotifiedState; + std::optional lastNotifiedState; MidiDeviceListConnection::Key key = 0; };