Thread overview | |||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
August 17, 2017 Exception chaining and collectException | ||||
---|---|---|---|---|
| ||||
Code: -------- import std.exception : collectException; import std.stdio; class MyException : Exception { this() { super("MYMY"); } } void f() { throw new MyException(); } struct S { ~this() { auto e = collectException!MyException(f()); writefln("Collected: %s (%s)", typeid(e).toString, e.msg); } void method() { throw new Exception("Dumb error"); } } void main() { try { S s; s.method(); } catch (Exception e) { writefln("Caught: %s (%s) (next=%s)", typeid(e).toString, e.msg, e.next ? e.next.toString : "null"); } } -------- Expected output: collectException should collect MyException while "Dumb error" is in transit, and the output should contain a "Collected:" line. Actual behaviour: collectException doesn't work as advertised; MyException gets chained to the Exception in transit, and the "Collected:" line is never printed. If we change the collectException call to: auto e = collectException!Exception(f()); then it *does* work as advertised: the MyException instance is not chained, but is correctly collected by collectException. Why??? The code in question is reduced from a larger project where the dtor needs to do some non-trivial cleanup, but needs to ignore certain errors that may occur during cleanup. So it needs collectException to catch only certain subclasses of Exception, rather than all Exceptions. But the above inconsistent behaviour hampers this. Investigating the implementation of collectException, it seems that all it does is to use a try-catch block to catch an exception of the requested type. So the question becomes, why does the catch block *not* catch the instance of MyException when another exception is in transit?! T -- Gone Chopin. Bach in a minuet. |
August 17, 2017 Re: Exception chaining and collectException | ||||
---|---|---|---|---|
| ||||
Posted in reply to H. S. Teoh | Chained exceptions are a good idea, but are more or less a disaster: 1. No other language does chained exceptions 2. Attempting to hammer D chained exceptions into other language schemes (such as C++) makes for lots of unfun hours attempting to decode undocumented behavior in those other schemes 3. Makes D exceptions incompatible with other language exceptions and their infrastructure 4. Are incomprehensibly implemented (I defy anyone to explain how the test cases in the test suite are actually supposed to work) 5. Are more or less incompatible with non-GC memory allocation I'd like to remove them from D. I recommend *not* designing any program that requires them. |
August 18, 2017 Re: Exception chaining and collectException | ||||
---|---|---|---|---|
| ||||
Posted in reply to Walter Bright | On Friday, 18 August 2017 at 03:31:38 UTC, Walter Bright wrote: > Chained exceptions are a good idea, but are more or less a disaster: > > 1. No other language does chained exceptions > > 2. Attempting to hammer D chained exceptions into other language schemes (such as C++) makes for lots of unfun hours attempting to decode undocumented behavior in those other schemes > > 3. Makes D exceptions incompatible with other language exceptions and their infrastructure > > 4. Are incomprehensibly implemented (I defy anyone to explain how the test cases in the test suite are actually supposed to work) Well, I wrote them, so I can explain that. The problem is that the idea that you can form a "chain" of exceptions turns out to be naive. What if a chained exception needs to get chained to another chained exception? And that then needs to be chained to another exception? It forms a tree! That's why the test cases are so complicated. So to a large extent, this extremely obscure corner case destroys the elegance of the concept. Secondly, exception handling in windows is practically undocumented. Certainly it's not documented in a single place. When I began to implement it, I feared it might be impossible. There isn't any guarantee that exception chaining can actually be implemented on all platforms. > 5. Are more or less incompatible with non-GC memory allocation > > I'd like to remove them from D. > > I recommend *not* designing any program that requires them. I invested quite a lot personally in implementing chained exceptions. But I agree with you. I was actually quite proud that I worked out the nasty corner cases during the initial implementation. As far as I can tell, problems with chained exceptions are not because of bugs and implementation issues, but because of problems with the concept itself. I think it's just a bit too clever. |
August 18, 2017 Re: Exception chaining and collectException | ||||
---|---|---|---|---|
| ||||
Posted in reply to Don Clugston | On Friday, 18 August 2017 at 09:09:47 UTC, Don Clugston wrote: > > Secondly, exception handling in windows is practically undocumented. Certainly it's not documented in a single place. When I began to implement it, I feared it might be impossible. There isn't any guarantee that exception chaining can actually be implemented on all platforms. I had actually tested the above on Windows with DMD 2.075.1 and got the expected behavior, not the buggy behavior. > > I invested quite a lot personally in implementing chained exceptions. But I agree with you. > I was actually quite proud that I worked out the nasty corner cases during the initial implementation. As far as I can tell, problems with chained exceptions are not because of bugs and implementation issues, but because of problems with the concept itself. > > I think it's just a bit too clever. Do you mind pointing me in the direction of where chained exceptions are explained? |
August 18, 2017 Re: Exception chaining and collectException | ||||
---|---|---|---|---|
| ||||
Posted in reply to Walter Bright | On Friday, 18 August 2017 at 03:31:38 UTC, Walter Bright wrote:
> Chained exceptions are a good idea, but are more or less a disaster:
>
> 1. No other language does chained exceptions
>
> 2. Attempting to hammer D chained exceptions into other language schemes (such as C++) makes for lots of unfun hours attempting to decode undocumented behavior in those other schemes
>
> 3. Makes D exceptions incompatible with other language exceptions and their infrastructure
>
> 4. Are incomprehensibly implemented (I defy anyone to explain how the test cases in the test suite are actually supposed to work)
>
> 5. Are more or less incompatible with non-GC memory allocation
>
> I'd like to remove them from D.
>
> I recommend *not* designing any program that requires them.
If we are to remove them, what happens when exceptions would normally chain?
-Steve
|
August 18, 2017 Re: Exception chaining and collectException | ||||
---|---|---|---|---|
| ||||
Posted in reply to Steven Schveighoffer | On 8/18/2017 5:07 AM, Steven Schveighoffer wrote: > If we are to remove them, what happens when exceptions would normally chain? In C++, throwing an exception while unwinding is a fatal error. More information: https://stackoverflow.com/questions/130117/throwing-exceptions-out-of-a-destructor |
August 18, 2017 Re: Exception chaining and collectException | ||||
---|---|---|---|---|
| ||||
Posted in reply to Don Clugston | On 8/18/2017 2:09 AM, Don Clugston wrote: > I invested quite a lot personally in implementing chained exceptions. But I agree with you. > I was actually quite proud that I worked out the nasty corner cases during the initial implementation. As far as I can tell, problems with chained exceptions are not because of bugs and implementation issues, but because of problems with the concept itself. > > I think it's just a bit too clever. Thanks for the explanation. When I decided to support Dwarf exceptions, I spent a lot of time trying to match that behavior. We've all invested lots of time in things that didn't pay off. We mustn't get trapped by the sunk cost fallacy: https://en.wikipedia.org/wiki/Sunk_cost and I'm glad you're ok with that! |
August 19, 2017 Re: Exception chaining and collectException | ||||
---|---|---|---|---|
| ||||
Posted in reply to Walter Bright | On Friday, 18 August 2017 at 22:51:35 UTC, Walter Bright wrote: > On 8/18/2017 5:07 AM, Steven Schveighoffer wrote: >> If we are to remove them, what happens when exceptions would normally chain? > > In C++, throwing an exception while unwinding is a fatal error. > Well, you still can throw it, but you're not allowed to let it escape the destructor (you need to catch them before they would chain). C++ also provides a way to inspect if you're in the middle of the stack unwinding caused by an exception, to make this a bit more controllable, and I would think we should provide the similar primitive: http://en.cppreference.com/w/cpp/error/uncaught_exception. |
August 21, 2017 Re: Exception chaining and collectException | ||||
---|---|---|---|---|
| ||||
Posted in reply to Nemanja Boric | On Sat, Aug 19, 2017 at 08:58:51PM +0000, Nemanja Boric via Digitalmars-d wrote: > On Friday, 18 August 2017 at 22:51:35 UTC, Walter Bright wrote: > > On 8/18/2017 5:07 AM, Steven Schveighoffer wrote: > > > If we are to remove them, what happens when exceptions would normally chain? > > > > In C++, throwing an exception while unwinding is a fatal error. > > > > Well, you still can throw it, but you're not allowed to let it escape the destructor (you need to catch them before they would chain). This was what I was trying to do: wrap some code in a try-catch in the dtor so that any exceptions thrown won't escape the dtor. However, the current inconsistent behaviour is making this difficult. The same dtor behaves differently depending on whether it was called from a normal end of scope, or while an Exception is in transit. I.e., when called normally, the catch clause catches MyException, but when another Exception is in transit, the catch clause fails to catch MyException (yet it does catch the base class Exception, a rather strange behaviour). T -- The most powerful one-line C program: #include "/dev/tty" -- IOCCC |
August 21, 2017 Re: Exception chaining and collectException | ||||
---|---|---|---|---|
| ||||
Posted in reply to H. S. Teoh | On 08/17/2017 02:48 PM, H. S. Teoh via Digitalmars-d wrote: > So the question becomes, why does the catch block *not* > catch the instance of MyException when another exception is in transit?! I caught (!) the same or similar behavior last year: https://issues.dlang.org/show_bug.cgi?id=16177 Ali |
Copyright © 1999-2021 by the D Language Foundation