Jump to page: 1 2
Thread overview
[Issue 19602] Under some circumstances: throwing Error subclasses unwinds without invoking dtors
Jan 21, 2019
Eyal
Jan 21, 2019
Eyal
Jan 21, 2019
Baruch Even
Jan 22, 2019
Eyal
Jan 22, 2019
Mathias LANG
Jan 22, 2019
Eyal
Jan 22, 2019
Eyal
Jan 22, 2019
Jacob Carlborg
Jan 22, 2019
Mathias LANG
Jan 22, 2019
Jacob Carlborg
Jan 22, 2019
Eyal
Mar 16, 2019
Walter Bright
Mar 17, 2019
Eyal
Mar 17, 2019
Jacob Carlborg
January 21, 2019
https://issues.dlang.org/show_bug.cgi?id=19602

--- Comment #1 from Eyal <eyal@weka.io> ---
If "Errors" mean "bugs" - then it should not unwind the stack and allow catch() handlers to catch them and resume execution, as dtors will be skipped.

If error throwing is fine, then "nothrow" should NOT imply no auto-generated exception handling code. It becomes useful only as a declaration of intent for the user, and not useful to the compiler.

As long as this bug exists, there's a choice between these 2 options:

* Errors should never really be caught - as they run in a completely broken state.

* Destructors cannot be trusted in the general case.

I see 2 possible fixes:

* Ignore nothrow in the compiler codegen. Assume errors can always be thrown, even in nothrow (indeed they can).

* Replace throwing/catching Errors with a different mechanism to signal/handle errors without incorrect stack unwinding.

--
January 21, 2019
https://issues.dlang.org/show_bug.cgi?id=19602

Eyal <eyal@weka.io> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |eyal@weka.io

--
January 21, 2019
https://issues.dlang.org/show_bug.cgi?id=19602

Baruch Even <baruch@weka.io> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |baruch@weka.io

--
January 22, 2019
https://issues.dlang.org/show_bug.cgi?id=19602

Eyal <eyal@weka.io> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
           Keywords|                            |industry
           Priority|P3                          |P2
           Severity|enhancement                 |critical

--
January 22, 2019
https://issues.dlang.org/show_bug.cgi?id=19602

Mathias LANG <pro.mathias.lang@gmail.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |pro.mathias.lang@gmail.com
           Severity|critical                    |normal

--- Comment #2 from Mathias LANG <pro.mathias.lang@gmail.com> ---
This behavior is documented in the language specs since the very beginning of D2.

In fact, there is currently a bug opened by Walter because dtors and `scope`
statements are executed: https://issues.dlang.org/show_bug.cgi?id=17494
In addition, there is a PR to fix said issue:
https://github.com/dlang/dmd/pull/6896

There is still value in catching `Error` though: as a last resort mesure: catch, log & abort is one thing, and catching at the top of a thread/fiber to avoid the program termination is another.

Note that if `nothrow` applied to Error, the attribute would be essentially useless: `assert`, `new`, `switch`, slice casts and many other things could not be `nothrow`.

--
January 22, 2019
https://issues.dlang.org/show_bug.cgi?id=19602

--- Comment #3 from Eyal <eyal@weka.io> ---
If you catch to *avoid* program termination -- you leak all destructors, leaving program in a likely-corrupt state.

Note I did not suggest `nothrow` would apply to Error.

Rather, I suggested that dtors *always* execute, even when Errors are thrown from `nothrow` functions. Or: replacing the corrupt-unwinding of Errors with a different error signaling mechanism.

Currently, dtors *usually* execute, depending on arbitrary context. Catching Error (even unintentionally via catching Throwable) leads to cleanups in D being unreliable, and corruption being very easy.

--
January 22, 2019
https://issues.dlang.org/show_bug.cgi?id=19602

--- Comment #4 from Eyal <eyal@weka.io> ---
Just to clarify on my last point, if "auto sneakyThrow" is changed to "void sneakyThrow" -- it DOES run the dtor! Because it is no longer inferred to be nothrow.

This is a really unpredictable semantics for a simple program, doesn't feel at all reasonable in a language that desires safety.

--
January 22, 2019
https://issues.dlang.org/show_bug.cgi?id=19602

Jacob Carlborg <doob@me.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |doob@me.com

--- Comment #5 from Jacob Carlborg <doob@me.com> ---
(In reply to Mathias LANG from comment #2)

> There is still value in catching `Error` though: as a last resort mesure: catch, log & abort is one thing, and catching at the top of a thread/fiber to avoid the program termination is another.

For a unit test framework it's useful to catch AssertError to be able to continue running other tests.

--
January 22, 2019
https://issues.dlang.org/show_bug.cgi?id=19602

--- Comment #6 from Mathias LANG <pro.mathias.lang@gmail.com> ---
(In reply to Jacob Carlborg from comment #5)
>
> For a unit test framework it's useful to catch AssertError to be able to continue running other tests.

Yep, however that's covered by the specs:

> Individual tests are specified in the unit test using spec/expression, AssertExpressions. Unlike AssertExpressions used elsewhere, the assert is not assumed to hold, and upon assert failure the program is still in a defined state.

https://dlang.org/spec/unittest.html

(In reply to Eyal from comment #4)
> Just to clarify on my last point, if "auto sneakyThrow" is changed to "void sneakyThrow" -- it DOES run the dtor! Because it is no longer inferred to be nothrow.
> 
> This is a really unpredictable semantics for a simple program, doesn't feel at all reasonable in a language that desires safety.


And that is the real bug, which is reported as 17494

--
January 22, 2019
https://issues.dlang.org/show_bug.cgi?id=19602

--- Comment #7 from Jacob Carlborg <doob@me.com> ---
(In reply to Mathias LANG from comment #6)

> Yep, however that's covered by the specs:
> 
> > Individual tests are specified in the unit test using spec/expression, AssertExpressions. Unlike AssertExpressions used elsewhere, the assert is not assumed to hold, and upon assert failure the program is still in a defined state.
> 
> https://dlang.org/spec/unittest.html

It's difficult to know if the AssertError was thrown from a "unittest" block or from somewhere else.

--
« First   ‹ Prev
1 2