MessageManagerLock needed for actionListener?

I have a user who’s experiencing random crashes on mac and the crash dumps are all over the place but are all related to component painting. I cannot reproduce.

I use the actionListener and broadcaster heavily in my application for sending messages around. Often I’ll update some data in another thread, broadcast a message and listening components will update themselves. Is it possible that this is a bad pattern? Or do I need to add a messageManagerLock at the start of each of the places where I update the UI in my actionListeners?

Here is one of the dumps in case anyone is curious.

Thread 0 Crashed:: JUCE Message Thread  Dispatch queue:
0   libsystem_malloc.dylib        	0x00007fff70b002f3 nanov2_allocate_from_block + 615
1   libsystem_malloc.dylib        	0x00007fff70aff969 nanov2_allocate + 130
2   libsystem_malloc.dylib        	0x00007fff70b007dd nanov2_calloc + 81
3   libsystem_malloc.dylib        	0x00007fff70af5444 malloc_zone_calloc + 99
4   libsystem_malloc.dylib        	0x00007fff70af53c4 calloc + 30
5      	0x00007fff449220cd +[__NSArrayM __new:::] + 127
6              	0x00007fff41f41798 -[NSApplication _copyWindows] + 164
7              	0x00007fff41f416df -[NSApplication windows] + 22
8   com.GroupeBeatConnect.BeatConnect	0x0000000106a4da58 juce::NSViewComponentPeer::areAnyWindowsInLiveResize() + 88
9   com.GroupeBeatConnect.BeatConnect	0x0000000106a4c06d juce::NSViewComponentPeer::repaint(juce::Rectangle<int> const&) + 109
10  com.GroupeBeatConnect.BeatConnect	0x0000000106920205 juce::Component::internalRepaintUnchecked(juce::Rectangle<int>, bool) + 789
11  com.GroupeBeatConnect.BeatConnect	0x000000010691ffe3 juce::Component::internalRepaintUnchecked(juce::Rectangle<int>, bool) + 243
12  com.GroupeBeatConnect.BeatConnect	0x000000010691b7de juce::Component::setBounds(int, int, int, int) + 462
13  com.GroupeBeatConnect.BeatConnect	0x00000001065b92b3 ViewManager::OpenView(juce::String, int, int) + 307
14  com.GroupeBeatConnect.BeatConnect	0x00000001065fc711 SequencerView::actionListenerCallback(juce::String const&) + 3073
15  com.GroupeBeatConnect.BeatConnect	0x000000010683f957 juce::MessageQueue::deliverNextMessage() + 87
16  com.GroupeBeatConnect.BeatConnect	0x000000010683f85c juce::MessageQueue::runLoopSourceCallback(void*) + 28
17      	0x00007fff4496539b __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 17
18      	0x00007fff44965341 __CFRunLoopDoSource0 + 108
19      	0x00007fff44948c0b __CFRunLoopDoSources0 + 195
20      	0x00007fff449481d5 __CFRunLoopRun + 1189
21      	0x00007fff44947ade CFRunLoopRunSpecific + 455
22           	0x00007fff43ba61ab RunCurrentEventLoopInMode + 292
23           	0x00007fff43ba5ee5 ReceiveNextEventCommon + 603
24           	0x00007fff43ba5c76 _BlockUntilNextEventMatchingListInModeWithFilter + 64
25              	0x00007fff41f3de89 _DPSNextEvent + 1135
26              	0x00007fff41f3cb77 -[NSApplication(NSEvent) _nextEventMatchingEventMask:untilDate:inMode:dequeue:] + 1361
27              	0x00007fff41f36c94 -[NSApplication run] + 699
28  com.GroupeBeatConnect.BeatConnectDaw	0x000000010143ca8f main + 191
29  libdyld.dylib                 	0x00007fff709483d5 start + 1

You need to update your UI Asynchronously


Wait am I not? Isn’t that how the action Listener works or is there another type of message dispatch I should be using?

I had exactly the same issues. You need to use the juce::AsyncUpdater or a juce::Timer on the component to dispatch it into the UI thread when you received the action.

Edit: there is also a one-line function that dispatch into the UI thread with a function. I will try to find out.

Edit2: No need for the AsyncUpdater. ActionListener messages are already in the main thread.

It looks to me like the action listener callback should always be called on the main thread, as long as it is triggered with ActionBroadcaster::sendActionMessage. The stack trace posted earlier is apparently from the main message thread, but the crash is happening while calling [NSApp windows].

Given that the crash is happening inside an OS function which should be stable, I’d guess that an error happens earlier in the program, but it’s taking a little while to manifest as a crash.

Have you tried testing with Address Sanitizer?

Thanks for clarifying. I was wrong… the code looks right and i also have done some tests. Looks like its safe to remove the juce::AsyncUpdater now :slight_smile:

You can easy verify it like this:


Thanks for the response. I’m relieved to know I won’t need to refactor that code. I’ve never heard of address sanitizer but I suspect you may be right as I’ve run into similar issues not so long ago due to casting invalid pointers.

Appreciate the help and the tips!