Bug with juce::MidiOutput::createNewDevice

Hi everyone!

We’ve encountered a strange bug, and we suspect it might be an issue with Logic Pro, macOS or JUCE.
It only reproduces in Logic Pro and on Intel processors.

In our case:

  • MacBook Pro 2018
  • macOS Sonoma 14.6.1
  • JUCE 8.0.4
  • Logic Pro 10.8.1

We managed to reproduce the issue in a minimal project using JUCE examples.
Here’s the gist of the bug:
ComboBox components stop working, and multiple asserts like JUCE_ASSERT_MESSAGE_THREAD are thrown after creating a virtual MIDI device with juce::MidiOutput::createNewDevice("device");.

The issue only occurs when opening two instances of the plugin in two simultaneously opened Logic Pro projects.

The problem seems rare, and we could only reproduce it on Intel, but one of our users experienced similar behavior on M1. Unfortunately, we couldn’t reproduce it ourselves on M1.

Has anyone encountered anything similar or can at least point us in the right direction? Thanks in advance for any suggestions!

Are you able to reproduce the problem in a minimal plugin project? If you can share code that demonstrates the problem, it will be much easier for us to debug the issue.

It might also be interesting to see whether the issue is present on macOS 15.1 and Logic 11. If not, that might indicate that the issue was caused by a bug that has been fixed in newer releases.

1 Like

Yes, sure — it’s a minimal project created from JUCE examples
Archive.zip (10.4 KB)

Thanks for the example code, that’s really helpful.

Unfortunately, I’m not able to reproduce the behaviour you describe with combo boxes, but I do see some assertions on instantiating the plugin.

I can fix the assertions by changing the lastNotifiedState data member near the end of juce_MidiDeviceListConnectionBroadcaster.cpp like so:

// old
State lastNotifiedState;
// new
std::optional<State> lastNotifiedState;

Please could you try out that change and check whether you still see the issue with combo boxes?

1 Like

Thanks a lot, but unfortunately, it does not help. The ComboBox is still broken in the second project, and we still have a lot of assertions in the second project.

Maybe the list below can help:

  • JUCE Assertion failure in juce_Component.cpp:284
  • JUCE Assertion failure in juce_Component.cpp:365
  • JUCE Assertion failure in juce_Component.cpp:480
  • JUCE Assertion failure in juce_Component.cpp:793
  • JUCE Assertion failure in juce_Component.cpp:1147
  • JUCE Assertion failure in juce_Component.cpp:1607
  • JUCE Assertion failure in juce_Component.cpp:1225
  • JUCE Assertion failure in juce_Component.cpp:2063
  • JUCE Assertion failure in juce_Component.cpp:2686
  • JUCE Assertion failure in juce_Desktop.cpp:82
  • JUCE Assertion failure in juce_Desktop.cpp:263
  • JUCE Assertion failure in juce_Timer.cpp:367

(There are a lot of these, maybe 100 or 200. We have removed duplicates.)

OK, thanks for trying that.

Please could you send me a call stack for the very first assertion that’s hit? If you’d prefer not to share it publicly you can send it as a direct message, or put it in an email to info [at] juce [dot] com.

1 Like

stacktrace.txt (1.3 KB)

This is
Thread-1-<com.apple.main-thread>

Thanks, that sounds like some other thread might be getting incorrectly marked as the main thread.

Could you try putting a breakpoint in MessageManager::setCurrentThreadAsMessageThread(), and check whether it gets called from a background thread when adding a second plugin instance? If so, please post a stack trace.

1 Like

It’s never called; breakpoints do not hit.

Strange, I’ll try to investigate here.

1 Like

Just to make sure — the second plugin instance runs from a second Logic project that’s open at the same time as the first one.

Sorry, I’d missed that detail. I’ll try that.

1 Like

Maybe it can help: here is the full Logic call graph with two simultaneously opened projects, each with an instance of the plugin.

Call graph.txt (63.0 KB)

I think what’s happening is:

  • When Logic has multiple projects open, it creates/destroys plugin instances when switching between those projects, so that it only has the plugin instances for the active project open at any time.
  • When creating a new blank project while another project is open, all plugin instances in the existing project will be destroyed when creating the blank project. This may destroy JUCE’s message manager instance for any JUCE plugins.
  • If the MIDI configuration change callback fires on a background thread while there’s no message manager active, the message manager may incorrectly be created on that background thread.

This patch seems to resolve the issue for me. Please try it out and let me know how you get on.

logicmidi.patch (2.5 KB)

1 Like

Hooray, it works!
No assertions, and the combobox is working fine now.
Thank you so much!

Will these changes be in the next JUCE update?
Do you know any potential release dates if yes?
We need to decide whether to integrate this patch into our CI script or wait for the official update if it’s coming soon

Anyway, thanks again for your help

1 Like

I expect the change will be on the develop branch shortly, but we don’t have plans for a master-branch release at this point.

Glad the fix works for you!

1 Like

The patch is now merged on the develop branch:

1 Like

Thanks a lot! I think this is really fast! :slight_smile: