jaydee
December 10, 2008, 1:16am
1
I think there may be a little problem with the…
void* MessageManager::callFunctionOnMessageThread (MessageCallbackFunction* callback,
void* data) in the tip
When its not called from the message thread.
As an example…create a thread and throw an AlertWindow::showMessageBox in its run method.
I crash before the performCallback: is executed.
I’ll try to debug more and post more details…
jaydee
December 10, 2008, 1:20am
2
Thread 5 Crashed:
0 libobjc.A.dylib 0x91a8768c objc_msgSend + 28
1 com.apple.Foundation 0x9142f648 -[NSObject(NSThreadPerformAdditions) performSelectorOnMainThread:withObject:waitUntilDone:] + 184
2 com.sm.rip 0x002d80a7 juce::MessageManager::callFunctionOnMessageThread(void* (*)(void*), void*) + 125
3 com.sm.rip 0x001debd9 juce::AlertWindowInfo::run() const + 47
4 com.sm.rip 0x001dc707 juce::AlertWindow::showMessageBox(juce::AlertWindow::AlertIconType, juce::String const&, juce::String const&, juce::String const&) + 179
juceAppDelegate is inited and valid…I put a breakpoint on dealloc and it hasn’t been hit
jaydee
December 10, 2008, 9:53am
3
The problem it appears is with
CallbackMessagePayload
changing the code to
[juceAppDelegate performSelectorOnMainThread: @selector (performCallback:)
withObject: nil// (id) &cmp
waitUntilDone: YES];
At least allows the performCallback: function to be called.
Does performSelectorOnMainThread try to retain the object I wonder…(casting the struct to an id would be a no-no in that case)
jaydee
December 10, 2008, 10:00am
4
jaydee
December 10, 2008, 10:13am
5
Also, for those using the tip and NOT the amalgamated file. If you are not doing a clean build, TOUCH juce_mac_NativeCode.mm before building.
I’ve noticed a few times i’ve grabbed updates from the tip and the build went super fast(as though no changes had been made), so I got in the habit of doing a clean before every build. However while debugging this problem, I noticed the changes I was making to the source file weren’t being compiled. Sure enough Jules put a little comment at the top…
// (This file gets included by juce_mac_NativeCode.mm, rather than being
// compiled on its own).
#ifdef JUCE_INCLUDED_FILE
And after I touched juce_mac_NativeCode.mm all compiled as it should!
jaydee
December 10, 2008, 10:46am
6
How about this as a little fix?
[code]void* MessageManager::callFunctionOnMessageThread (MessageCallbackFunction* callback,
void* data)
{
if (isThisTheMessageThread())
{
return (*callback) (data);
}
else
{
CallbackMessagePayload cmp;
cmp.function = callback;
cmp.parameter = data;
cmp.result = 0;
cmp.hasBeenExecuted = false;
[juceAppDelegate performSelectorOnMainThread: @selector (performCallback:)
withObject: [NSData dataWithBytesNoCopy:&cmp length:sizeof(CallbackMessagePayload)]
waitUntilDone: YES];
return cmp.result;
}
}[/code]
- (void) performCallback: (id) info
{
CallbackMessagePayload* pl=0;
if ([info isKindOfClass:[NSData class]])
pl= (CallbackMessagePayload*) [(NSData*)info bytes];
if (pl != 0)
{
pl->result = (*pl->function) (pl->parameter);
pl->hasBeenExecuted = true;
}
}
jaydee
December 10, 2008, 10:57am
7
OK—FINAL POST!
Does callFunctionOnMessageThread need an AutoPool Julian? As its called from a thread, the user may not have a pool in place right?
void* MessageManager::callFunctionOnMessageThread (MessageCallbackFunction* callback,
void* data)
{
if (isThisTheMessageThread())
{
return (*callback) (data);
}
else
{
const ScopedAutoReleasePool pool;
CallbackMessagePayload cmp;
cmp.function = callback;
cmp.parameter = data;
cmp.result = 0;
cmp.hasBeenExecuted = false;
[juceAppDelegate performSelectorOnMainThread: @selector (performCallback:)
withObject: [NSData dataWithBytesNoCopy:&cmp length:sizeof(CallbackMessagePayload)]
waitUntilDone: YES];
return cmp.result;
}
}
Better to be safe than sorry!
jules
December 10, 2008, 11:45am
8
jaydee
December 10, 2008, 5:40pm
9
I see the commit message in 634 addressing it, but mac_messageManager doesn’t seem to be affected.
Not a big deal for me, but thought i’d mention it anyways…
jules
December 11, 2008, 11:20am
10
Doh, sorry. Looks like I didn’t tick the right boxes and that file was missed out. It’s checked in now.
jaydee
January 1, 2009, 8:40pm
11
Sorry… this function needs a little fix…
void* MessageManager::callFunctionOnMessageThread (MessageCallbackFunction* callback,
void* data)
{
if (isThisTheMessageThread())
{
return (*callback) (data);
}
else
{
const ScopedAutoReleasePool pool;
CallbackMessagePayload cmp;
cmp.function = callback;
cmp.parameter = data;
cmp.result = 0;
cmp.hasBeenExecuted = false;
[juceAppDelegate performSelectorOnMainThread: @selector (performCallback:)
withObject: [NSData dataWithBytesNoCopy: &cmp
length: sizeof (cmp) freeWhenDone:NO]
waitUntilDone: YES];
return cmp.result;
}
}
(Needs the freeWhenDone:NO added to the function call, otherwise the autorelease pool tries to free cmp and spits out a
malloc: *** error for object 0xb05fae6c: Non-aligned pointer being freed
*** set a breakpoint in malloc_error_break to debug
jules
January 2, 2009, 9:41am
12
ah, quite right - thanks for that!