“Signals and exceptions don’t mix well, and should be considered seperately. While you can define an exception-based wrapper for signals, such code is not portable, because C++ does not guarantee that a signal-handling function is able to interact with any other part of a program. Creating a signal handler that throws an exception, for example, is undefined behavior in Standard C++.”
Thankfully this is not so true anymore. I can attest from experience that Solaris and HPUX have allowed you to do this for a while, but GNU/Linux has always been a problem child. Thankfully a lot of effort has recently been put into GCC, allowing you to trigger an exception from within syncronous signals, thus bridging the gap, sadly however the x86 platform does not seem to be one of the architectures fixed, and the gcc-java compiler only seems to be able to do this by rewriting the stack frame from within the signal.
If you are using GCC, you cannot expect to throw exceptions through arbitrary C library functions like raise(). If you don’t do this and want to handle asynchronous exceptions, you need at least -fnon-call-exceptions in all code that might raise synchronous signals and/or -fasynchronous-unwind-tables in all code that might be interrupted by asynchronous signals you want to throw from (obviously you have to make sure that you don’t throw while the asynchronous signal interrupted some function without exception support).
So far using -fnon-call-exceptions with gcc3.4 on x86 I have managed to allow a signal to throw an exception, but then it ends up in the designated terminate and atexit code. Whoopdy do! But catching that exception in the context that generated the signal is still out of my reach. This is obviously because the signal is happening on a different stack. If you read the default behavior for a throw() with no catch, then the issue seems clearer.
[UPDATE] Time to give up on this – even -fsignaling-nans has no effect. I have fixed the major problem in that some of my test cases were loosing the plot every day and logging an infinite number of execptions to a finite harddrive. So its back to the parser.
Output from test_mw_unix
! MAIN P00000000 M00000000 12:26:11.941 00016384 _ + spawning as daemon disabled by default – use command line argument ‘–enable-daemon’ to spawn as a daemon
! MAIN P00000000 M00000000 12:26:11.941 EST 00016384 _ + using local timezone ‘EST’
! MAIN P00000000 M00000000 12:26:11.942 EST 00016384 _ + initialising metawrap engine.
! BOOT P00000000 M00000000 12:26:11.943 EST 00016384 _ + startup
! INIT P00000000 M00000000 12:26:11.943 EST 00016384 _ + starting up low level services
! BOOT P00000000 M00000000 12:26:11.943 EST 00016384 _ + setting random seed
! INIT P00000000 M00000000 12:26:11.945 EST 00016384 _ + root_cluster_key loaded
! INIT P00000000 M00000000 12:26:11.952 EST 00016384 _ + root_cluster_key validated
! INIT P00000000 M00000000 12:26:11.952 EST 00016384 _ + scanning for plugins
+ running test ‘test_mw_unix’
Using unix timer ‘”CLOCK_THREAD_CPUTIME_ID”‘
test ‘mw_unix compiles’ PASSED
! MAIN P00000000 M00000000 12:26:11.045 EST 00016384 _ + TestClass
! MAIN P00000000 M00000000 12:26:11.045 EST 00016384 _ + throw exception.
test ‘MwUnix::signal::throw::1’ PASSED
! MAIN P00000000 M00000000 12:26:11.046 EST 00016384 _ + throw exception.
test ‘MwUnix::signal::throw::2’ PASSED
! MAIN P00000000 M00000000 12:26:11.046 EST 00016384 _ + cause SIGFPE.
! SIGH P00000000 M00000000 12:26:11.047 EST 00016384 _ SIGNAL [Floating point exception(8) occured [pid 20373 tid 16384], recovering]
! SIGH P00000000 M00000000 12:26:11.047 EST 00016384 _ + throwing exception
! MAIN P00000000 M00000000 12:26:11.048 EST 00016384 _ + terminate
This means that the last test failed and caused a complete abort.
Things to do – add ability to testcase system to register a testcase and report a failure if we do an ABEND.