Thread overview
Is it supposed to be safe to throw inside struct destructors?
Apr 07, 2014
Marco Leise
Apr 07, 2014
Dmitry Olshansky
Apr 07, 2014
monarch_dodra
Apr 07, 2014
Marco Leise
April 07, 2014
I would like to hear a definite answer on this. A failure in ~this() leaves the program in an undefined state. You cannot back out of returning from a function that needs to perform cleanup on stack structs. Constructors do not have this problem. With scope(failure) you can guard all resources and guarantee cleanup after an exception is thrown.

If we CAN throw in ~this(), the exception should (based on the fact that the program is now in an invalid state, like after a failed assertion or out-of-memory) be wrapped in something like a FinalizeError to tear down the whole program.

If not, then error reporting needs to be done in a "nothrow" context. This has far reaching consequences since typically error logging means doing I/O and I/O can fail and throw Exceptions. So either the logging calls in destructors would be wrapped in try-catch or there needs to be some printf() calls scattered in ~this().


References:
http://wiki.dlang.org/DIP44
http://forum.dlang.org/thread/op.vvek7te7tuzx1w@cybershadow.mshome.net?page=3#post-iqjhlc:241rde:241:40digitalmars.com
http://d.puremagic.com/issues/show_bug.cgi?id=4621

-- 
Marco

April 07, 2014
07-Apr-2014 12:33, Marco Leise пишет:
> I would like to hear a definite answer on this. A failure in
> ~this() leaves the program in an undefined state. You cannot
> back out of returning from a function that needs to perform
> cleanup on stack structs. Constructors do not have this
> problem. With scope(failure) you can guard all resources and
> guarantee cleanup after an exception is thrown.

There is exception chaining for that. All collateral exceptions get appended to a list. IIRC throw in a destructor while exception is in flight breaks out of this particular destructor, other if any are then executed in turn.

>
> If we CAN throw in ~this(), the exception should (based on
> the fact that the program is now in an invalid state, like
> after a failed assertion or out-of-memory) be wrapped in
> something like a FinalizeError to tear down the whole program.
>
> If not, then error reporting needs to be done in a "nothrow"
> context. This has far reaching consequences since typically
> error logging means doing I/O and I/O can fail and throw
> Exceptions. So either the logging calls in destructors
> would be wrapped in try-catch or there needs to be some
> printf() calls scattered in ~this().
>
>
> References:
> http://wiki.dlang.org/DIP44
> http://forum.dlang.org/thread/op.vvek7te7tuzx1w@cybershadow.mshome.net?page=3#post-iqjhlc:241rde:241:40digitalmars.com
> http://d.puremagic.com/issues/show_bug.cgi?id=4621
>


-- 
Dmitry Olshansky
April 07, 2014
On Monday, 7 April 2014 at 19:19:18 UTC, Dmitry Olshansky wrote:
> 07-Apr-2014 12:33, Marco Leise пишет:
>> I would like to hear a definite answer on this. A failure in
>> ~this() leaves the program in an undefined state. You cannot
>> back out of returning from a function that needs to perform
>> cleanup on stack structs. Constructors do not have this
>> problem. With scope(failure) you can guard all resources and
>> guarantee cleanup after an exception is thrown.
>
> There is exception chaining for that. All collateral exceptions get appended to a list. IIRC throw in a destructor while exception is in flight breaks out of this particular destructor, other if any are then executed in turn.

That's the theory, but in practice, throwing an exception allocates, and you can't allocate if you are in a GC collect cycle.

So it's kind of back to square 1 in terms of throwing in destructors: Don't do it :/
April 07, 2014
Am Mon, 07 Apr 2014 21:36:34 +0000
schrieb "monarch_dodra" <monarchdodra@gmail.com>:

> On Monday, 7 April 2014 at 19:19:18 UTC, Dmitry Olshansky wrote:
> > 07-Apr-2014 12:33, Marco Leise пишет:
> >> I would like to hear a definite answer on this. A failure in ~this() leaves the program in an undefined state. You cannot back out of returning from a function that needs to perform cleanup on stack structs. Constructors do not have this problem. With scope(failure) you can guard all resources and guarantee cleanup after an exception is thrown.
> >
> > There is exception chaining for that. All collateral exceptions get appended to a list. IIRC throw in a destructor while exception is in flight breaks out of this particular destructor, other if any are then executed in turn.
> 
> That's the theory, but in practice, throwing an exception allocates, and you can't allocate if you are in a GC collect cycle.
> 
> So it's kind of back to square 1 in terms of throwing in destructors: Don't do it :/

Aye!

-- 
Marco