www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Exception chaining

reply "monarch_dodra" <monarchdodra gmail.com> writes:
In one of my exception handling blocks, I call some code that 
could *also*, potentially throw (it's actually a loop, where each 
iteration can throw, but I have to do them *all*, meaning I need 
to handle *several* extra exceptions). I'm wondering what the 
"correct" way of handling both exceptions is.

We can chain them, but which comes first? Ideally, it'd be first 
in, first out, but given that exceptions make a singly linked 
list, pushing back is expensive (well, as expensive as it can get 
in exception handling code I guess).

It's actually the amount of code I'd have to put deploy to get 
the "end" of the original chain first (if it had some), then 
append the exception to to the chain, update the tail etc. Seems 
cumbersome.

Is there an "easy" or "built-in" way to same 
"myFirstException.append(newException)"?

Is it even worth doing it? I mean, after doing all this, I 
noticed that when an application dies due to an exception, it 
just ignores the chained exceptions... Kind of sad.

Has anybody ever chained exceptions? Has anybody ever cared about 
anything past the first exception when catching them?
Sep 13 2013
parent reply Sean Kelly <sean invisibleduck.org> writes:
On Sep 13, 2013, at 2:14 PM, monarch_dodra <monarchdodra gmail.com> =
wrote:

 In one of my exception handling blocks, I call some code that could =
*also*, potentially throw (it's actually a loop, where each iteration = can throw, but I have to do them *all*, meaning I need to handle = *several* extra exceptions). I'm wondering what the "correct" way of = handling both exceptions is.
=20
 We can chain them, but which comes first? Ideally, it'd be first in, =
first out, but given that exceptions make a singly linked list, pushing = back is expensive (well, as expensive as it can get in exception = handling code I guess). Exception chaining is actually built-in. I did some digging for an = official description, but couldn't find one. Here's a summary: If an Exception is thrown when an Exception or Error is already in = flight, it is considered collateral damage and appended to the chain = (built via Throwable.next). If an Error is thrown when an Exception is already in flight, it will = replace the in flight Exception and reference it via = Error.bypassedException. If an Error is thrown when an Error is already in flight, it will be = considered collateral damage and appended to the Throwable.next chain. So in the case where an Exception is thrown, more Exceptions are = generated as collateral damage, then an Error is thrown which bypasses = the in flight exception, and then more Exceptions and Errors are = generated as collateral damage, you can have one chain off the primary = Error and a second chain of the bypassedException. It's possible that = bit needs to be cleaned up so there's only one chain.=
Sep 13 2013
parent "monarch_dodra" <monarchdodra gmail.com> writes:
On Friday, 13 September 2013 at 23:58:33 UTC, Sean Kelly wrote:
 Exception chaining is actually built-in.  I did some digging 
 for an official description, but couldn't find one.  Here's a 
 summary:

 If an Exception is thrown when an Exception or Error is already 
 in flight, it is considered collateral damage and appended to 
 the chain (built via Throwable.next).

 If an Error is thrown when an Exception is already in flight, 
 it will replace the in flight Exception and reference it via 
 Error.bypassedException.

 If an Error is thrown when an Error is already in flight, it 
 will be considered collateral damage and appended to the 
 Throwable.next chain.
Hum. The problem here, is the concept of "in flight". It implies an exception is *currently* going up, and that the exceptions thrown come from automatically called destructor (or functions called by destructor). My problem though, is that I am already in an exception handling "block", so there is no "in flight" exception, just the exception that's in my handle. Here is a reduced pseudo code of what I have, where "doThem" needs to do "doIt" "n" times, but needs to "unDoIt" if an exception is thrown. My code looks like this: //-------- void doThem(size_t n) { size_t i; try { for ( ; i < n ; ++i) doIt(i); } catch (Exception e) { //Grab the tail. Throwable tail = e; while(tail.next !is null) tail = tail.next; try //Start cleaning up { //undo everything individually for ( --i ; i < n ; --i) { try unDoIt(i); //This is the actual call catch (Exception ee) tail = (tail.next = ee); } } catch (Error ee) //An Error! { //insert the current exception before the currently bypassed exceptions. tail = ee.bypassedException; ee.bypassedException = e; throw ee; } } } //-------- I think this is crazy. The two questions I have are: 1. Am I doing it right? 2. Should I even bother? Even dmd doesn't bother printing the chained exceptions on death. I mean, my code could just as well be: //---- void doThem(size_t n) { size_t i; try { for ( ; i < n ; ++i) doIt(i); } catch (Exception e) { for ( --i ; i < n ; --i) { try unDoIt(i); catch (Exception /+ee+/) {/+ignore ee+/} } } } //---- Much simpler! For a bit of context, the code I have in mind is static array postblit: Postblit each element. If this fails, then destroy all previously post-blitted elements.
Sep 14 2013