Exceptions mysteriously ignored in 64-bit builds


#1

Very strange issue with exceptions: add this code

void mouseUp(const MouseEvent &e) { fprintf(stderr, "throwing exception..\n"); throw std::out_of_range("byebye"); }

to any component of the JuceDemo. Build the app as a 32-bit i386, when the mouseUp callback is called, the exception is thrown and the application dies. Now build it as a 64-bit application, and the exception won’t be catched by juce, and it will not trigger anything, the application will just ignore it… Apparently it is catched by the event loop. Here is the call stack when the exception is thrown:

(gdb) catch throw
(gdb) catch catch
(gdb) where
#0  0x00007fff931f60e9 in __cxa_throw ()
#1  0x000000010003aa43 in WidgetsDemo::mouseUp (this=0x105040c00, e=@0x7fff5fbfd418) at /juce-git/juce/extras/JuceDemo/Builds/MacOSX/../../Source/demos/WidgetsDemo.cpp:1116
#2  0x00000001003c87e7 in juce::Component::internalMouseUp (this=0x105040c00, source=@0x101539150, relativePos=@0x7fff5fbfd4e0, time=@0x7fff5fbfd710, oldModifiers=@0x7fff5fbfd590) at juce_Component.cpp:2398
#3  0x0000000100547a90 in juce::MouseInputSourceInternal::sendMouseUp (this=0x101536560, comp=0x105040c00, screenPos=@0x7fff5fbfd588, time=@0x7fff5fbfd710, oldMods=@0x7fff5fbfd590) at juce_MouseInputSource.cpp:120
#4  0x0000000100547769 in juce::MouseInputSourceInternal::setButtons (this=0x101536560, screenPos=@0x7fff5fbfd680, time=@0x7fff5fbfd710, newButtonState=@0x7fff5fbfd708) at juce_MouseInputSource.cpp:158
#5  0x000000010049d36f in juce::MouseInputSourceInternal::handleEvent (this=0x101536560, newPeer=0x10153e1d0, positionWithinPeer=@0x7fff5fbfd7f8, time=@0x7fff5fbfd710, newMods=@0x7fff5fbfd708) at juce_MouseInputSource.cpp:278
#6  0x00000001003d0bdd in juce::MouseInputSource::handleEvent (this=0x101539150, peer=0x10153e1d0, positionWithinPeer=@0x7fff5fbfd7f8, time=1333306577427, mods=@0x100b67ad8) at juce_MouseInputSource.cpp:527
#7  0x0000000100477d31 in juce::ComponentPeer::handleMouseEvent (this=0x10153e1d0, touchIndex=0, positionWithinPeer=@0x7fff5fbfd7f8, newMods=@0x100b67ad8, time=1333306577427) at juce_ComponentPeer.cpp:92
#8  0x000000010048da84 in juce::NSViewComponentPeer::sendMouseEvent (this=0x10153e1d0, ev=0x10281df20) at juce_mac_NSViewComponentPeer.mm:1467
#9  0x000000010048dbcb in juce::NSViewComponentPeer::redirectMouseUp (this=0x10153e1d0, ev=0x10281df20) at juce_mac_NSViewComponentPeer.mm:1479
#10 0x000000010048838f in -[JuceNSView_2_0_19_JSLvvV6j asyncMouseUp:] (self=0x10153e270, _cmd=0x100929cdf, ev=0x10281df20) at juce_mac_NSViewComponentPeer.mm:503
#11 0x00007fff9064175d in -[NSObject performSelector:withObject:] ()
#12 0x00007fff91562d94 in __NSThreadPerformPerform ()
#13 0x00007fff905c06e1 in __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ ()
#14 0x00007fff905bff4d in __CFRunLoopDoSources0 ()
#15 0x00007fff905e6d39 in __CFRunLoopRun ()
#16 0x00007fff905e6676 in CFRunLoopRunSpecific ()
#17 0x00007fff94bf231f in RunCurrentEventLoopInMode ()
#18 0x00007fff94bf951b in ReceiveNextEventCommon ()
#19 0x00007fff94bf9456 in BlockUntilNextEventMatchingListInMode ()
#20 0x00007fff922e1f5d in _DPSNextEvent ()
#21 0x00007fff922e1861 in -[NSApplication nextEventMatchingMask:untilDate:inMode:dequeue:] ()
#22 0x00007fff922de19d in -[NSApplication run] ()
#23 0x00000001002a08ef in juce::MessageManager::runDispatchLoop (this=0x104c003f0) at juce_mac_MessageManager.mm:290
#24 0x00000001004854a7 in juce::JUCEApplication::main (commandLine=@0x7fff5fbff010) at juce_Application.cpp:211
#25 0x00000001004857c0 in juce::JUCEApplication::main (argc=1, argv=0x7fff5fbff088) at juce_Application.cpp:259
#26 0x0000000100001d53 in main (argc=1, argv=0x7fff5fbff088) at /juce-git/juce/extras/JuceDemo/Builds/MacOSX/../../Source/ApplicationStartup.cpp:160

and here is the call stack where the exception is catched:

#0 0x00007fff931f535e in __cxa_begin_catch () #1 0x00007fff91562fab in __NSThreadPerformPerform () #2 0x00007fff905c06e1 in __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ () #3 0x00007fff905bff4d in __CFRunLoopDoSources0 () #4 0x00007fff905e6d39 in __CFRunLoopRun () #5 0x00007fff905e6676 in CFRunLoopRunSpecific () #6 0x00007fff94bf231f in RunCurrentEventLoopInMode () #7 0x00007fff94bf951b in ReceiveNextEventCommon () #8 0x00007fff94bf9456 in BlockUntilNextEventMatchingListInMode () #9 0x00007fff922e1f5d in _DPSNextEvent () #10 0x00007fff922e1861 in -[NSApplication nextEventMatchingMask:untilDate:inMode:dequeue:] () #11 0x00007fff922de19d in -[NSApplication run] () #12 0x00000001002a08ef in juce::MessageManager::runDispatchLoop (this=0x102809f70) at juce_mac_MessageManager.mm:290 #13 0x00000001004854a7 in juce::JUCEApplication::main (commandLine=@0x7fff5fbff010) at juce_Application.cpp:211 #14 0x00000001004857c0 in juce::JUCEApplication::main (argc=1, argv=0x7fff5fbff088) at juce_Application.cpp:259 #15 0x0000000100001d53 in main (argc=1, argv=0x7fff5fbff088) at /juce-git/juce/extras/JuceDemo/Builds/MacOSX/../../Source/ApplicationStartup.cpp:160

This is specific to mouseUp events, it does not happen with mouseDown. It does not seem to depend on the compiler/sdk version . Really puzzling, but annoying as having exceptions silently ignored is definitively not a good thing…

This is on OSX Lion with latest git version.


#2

I’m a bit stumped by that… Is there perhaps an extra compiler flag needed to enable exceptions in a 64-bit build?


#3

I don’t know. They are enabled indeed, I can catch them in the ‘mouseUp’ event for example, but if I don’t, they are intercepted by cocoa (or is it corefoundation?) at the level of “__NSThreadPerformPerform” and silently discarded, while juce would catch them if they had propagated up to the ‘runDispatchLoop’ (or the default handler would catch them if JUCE_CATCH_UNHANDLED_EXCEPTIONS is 0)


#4

Is the exception being thrown across an Objective C function? I found this:

This Apple page documents exception handling differences between 32-bit and 64-bit (down at 64-bit Zero-Cost C+±Compatible Exceptions)

http://developer.apple.com/library/mac/#releasenotes/Cocoa/RN-ObjectiveC/_index.html


#5

Thanks TheVinn, these “64-bit Zero-Cost C+±Compatible Exceptions” look like they could be the explanation to this behaviour specific to 64-bit builds. Maybe the [NSApplication run] loop always catches all NSExceptions , and in 64-bit mode, this also includes traditional c++ exceptions.

However that does not explain why this issue happens only with mouseUp events, and not mouseDown :? And also I’m not sure of what should be done, adding a try / catch in the juce mouseup callback ? (and other callback where that may happen, I’m sure mouseUp is not the only one)