Thread overview | |||||||||
---|---|---|---|---|---|---|---|---|---|
|
December 12, 2016 Error and Exception chaining | ||||
---|---|---|---|---|
| ||||
I read https://dlang.org/spec/statement.html, which told me that Error is different in the way it's chained. But that is pretty vague, and I'm still confused. Can someone explain that using examples? Thanks. |
December 12, 2016 Re: Error and Exception chaining | ||||
---|---|---|---|---|
| ||||
Posted in reply to Yuxuan Shui | (Note: Looks like there is a bug regarding Error.bypassedException member. Would others please confirm.) On 12/12/2016 01:15 PM, Yuxuan Shui wrote: > I read https://dlang.org/spec/statement.html, which told me that Error > is different in the way it's chained. But that is pretty vague, and I'm > still confused. > > Can someone explain that using examples? > > Thanks. You're referring to "[Errors] bypass the normal chaining mechanism, such that the chain can only be caught by catching the first Error." What it means is that an Error cannot be a collateral of an Exception, hiding in its chain. So, when there is an Error that would otherwise be a collateral of an Exception, you cannot catch the original Exception. What is more importantly in-flight at that time is the Error. The following program causes a chain of exceptions: import std.stdio; import std.string; import std.range; class TestException : Exception { this(string msg) { const fullMmsg = format("%s: %s",typeof(this).stringof, msg); writefln("throwing '%s'", fullMmsg); super(fullMmsg); } } class TestError : Error { this(string msg) { const fullMmsg = format("%s: %s",typeof(this).stringof, msg); writefln("throwing '%s'", fullMmsg); super(fullMmsg); } } // Causes an exception chain where the node at index errorIndex is an // Error (others are all Exceptions). void causeExceptionChain(size_t chainLength, size_t errorIndex) { void throws(size_t n) { scope (exit) { const msg = format("%s", n); if (n == errorIndex) { throw new TestError(msg); } else { throw new TestException(msg); } } if (n != 0) { // Redundant 'return' keyword due to // https://issues.dlang.org/show_bug.cgi?id=16960 return throws(n - 1); } } throws(chainLength - 1); } void main() { try { // -1 would mean "no Error in the chain". Change this to a // number between 0 and 4 (inclusive) then you will realize // that the Exception below will not be caught. size_t errorIndex = -1; causeExceptionChain(5, errorIndex); } catch (Exception original) { writefln("Caught"); // Unrelated: If you're not familiar with the curly braces in // the for loop, see the Note under "The sections of the for // loop" section at http://ddili.org/ders/d.en/for.html for ({ size_t i; Throwable ex = original; } ex; ex = ex.next, ++i) { writeln(" ".replicate(i), ex.msg); } } } throwing 'TestException: 0' throwing 'TestException: 1' throwing 'TestException: 2' throwing 'TestException: 3' throwing 'TestException: 4' Caught TestException: 0 TestException: 1 TestException: 2 TestException: 3 TestException: 4 Make errorIndex something other than -1 e.g. 3 and you will see that the Exception cannot be caught. size_t errorIndex = 3; You get the usual stack trace of an uncaught exception. throwing 'TestException: 0' throwing 'TestException: 1' throwing 'TestException: 2' throwing 'TestError: 3' throwing 'TestException: 4' deneme.TestError@(0): TestError: 3 ---------------- [...] Then, replace Exception with Error in the catch clause, and you will see that Error is again caught. (Side note: Errors are not supposed to be caught by programs because the whole state of the program is in question.) catch (Error original) { // <-- Now Error // ... } You will see that Error is in its own chain. It will contain just Error 3 and Error 4: throwing 'TestException: 0' throwing 'TestException: 1' throwing 'TestException: 2' throwing 'TestError: 3' throwing 'TestException: 4' Caught TestError: 3 TestException: 4 Now you would hope to get the original bypassed Exception chain with the following code writefln("The bypassed exception was '%s'", original.bypassedException); But bypassedException member of Error is always null. Bug? Thank you, Ali |
December 12, 2016 Re: Error and Exception chaining | ||||
---|---|---|---|---|
| ||||
Posted in reply to Ali Çehreli | Thanks a lot for the explanation! On Monday, 12 December 2016 at 22:01:54 UTC, Ali Çehreli wrote: > (Note: Looks like there is a bug regarding Error.bypassedException member. Would others please confirm.) > > On 12/12/2016 01:15 PM, Yuxuan Shui wrote: > > [...] > that Error > > [...] > vague, and I'm > > [...] > > You're referring to "[Errors] bypass the normal chaining mechanism, such that the chain can only be caught by catching the first Error." What it means is that an Error cannot be a collateral of an Exception, hiding in its chain. So, when there is an Error that would otherwise be a collateral of an Exception, you cannot catch the original Exception. What is more importantly in-flight at that time is the Error. > But chaining Error to Error works just like chaining Exception to Exception? > > But bypassedException member of Error is always null. Bug? Did I just randomly found a bug? > > Thank you, > Ali |
December 12, 2016 Re: Error and Exception chaining | ||||
---|---|---|---|---|
| ||||
Posted in reply to Yuxuan Shui | On 12/12/2016 02:08 PM, Yuxuan Shui wrote: > Thanks a lot for the explanation! > > On Monday, 12 December 2016 at 22:01:54 UTC, Ali Çehreli wrote: >> (Note: Looks like there is a bug regarding Error.bypassedException >> member. Would others please confirm.) >> >> On 12/12/2016 01:15 PM, Yuxuan Shui wrote: >> > [...] >> that Error >> > [...] >> vague, and I'm >> > [...] >> >> You're referring to "[Errors] bypass the normal chaining mechanism, >> such that the chain can only be caught by catching the first Error." >> What it means is that an Error cannot be a collateral of an Exception, >> hiding in its chain. So, when there is an Error that would otherwise >> be a collateral of an Exception, you cannot catch the original >> Exception. What is more importantly in-flight at that time is the Error. >> > > But chaining Error to Error works just like chaining Exception to > Exception? Currently yes. Now this line in my versatile :o) program: if (n >= errorIndex) { Two Errors are chained: Caught TestError: 3 TestError: 4 However, there is the following ongoing thread claiming that it was a wrong decision: http://forum.dlang.org/post/o2n347$2i1g$1@digitalmars.com >> But bypassedException member of Error is always null. Bug? > > Did I just randomly found a bug? From what I could graps from that much of documentation, yes, it seems to be a bug. Ali |
December 12, 2016 Re: Error and Exception chaining | ||||
---|---|---|---|---|
| ||||
Posted in reply to Ali Çehreli | On Monday, 12 December 2016 at 22:13:59 UTC, Ali Çehreli wrote: > On 12/12/2016 02:08 PM, Yuxuan Shui wrote: > > [...] > wrote: > >> [...] > Error.bypassedException > >> [...] > mechanism, > >> [...] > Error." > >> [...] > Exception, > >> [...] > otherwise > >> [...] > original > >> [...] > is the Error. > > [...] > Exception to > > [...] > > Currently yes. Now this line in my versatile :o) program: > > if (n >= errorIndex) { > > Two Errors are chained: > > Caught > TestError: 3 > TestError: 4 > > However, there is the following ongoing thread claiming that it was a wrong decision: > > http://forum.dlang.org/post/o2n347$2i1g$1@digitalmars.com > > > [...] > > From what I could graps from that much of documentation, yes, it seems to be a bug. I did some testing and bypassedException is null in 2.072.1, but is not null in 2.070.2 > > Ali |
December 13, 2016 Re: Error and Exception chaining | ||||
---|---|---|---|---|
| ||||
Posted in reply to Yuxuan Shui | On Monday, 12 December 2016 at 22:35:22 UTC, Yuxuan Shui wrote:
> On Monday, 12 December 2016 at 22:13:59 UTC, Ali Çehreli wrote:
>> On 12/12/2016 02:08 PM, Yuxuan Shui wrote:
>> > [...]
>> wrote:
>> >> [...]
>> Error.bypassedException
>> >> [...]
>> mechanism,
>> >> [...]
>> Error."
>> >> [...]
>> Exception,
>> >> [...]
>> otherwise
>> >> [...]
>> original
>> >> [...]
>> is the Error.
>> > [...]
>> Exception to
>> > [...]
>>
>> Currently yes. Now this line in my versatile :o) program:
>>
>> if (n >= errorIndex) {
>>
>> Two Errors are chained:
>>
>> Caught
>> TestError: 3
>> TestError: 4
>>
>> However, there is the following ongoing thread claiming that it was a wrong decision:
>>
>> http://forum.dlang.org/post/o2n347$2i1g$1@digitalmars.com
>>
>> > [...]
>>
>> From what I could graps from that much of documentation, yes, it seems to be a bug.
>
> I did some testing and bypassedException is null in 2.072.1, but is not null in 2.070.2
>
>>
>> Ali
The unwind process seem to stop one level too early, causing language_specific_data to be different, causing __dmd_personality_v0 to not chain exception into .bypassException.
|
December 13, 2016 Re: Error and Exception chaining | ||||
---|---|---|---|---|
| ||||
Posted in reply to Yuxuan Shui | On Tuesday, 13 December 2016 at 00:33:58 UTC, Yuxuan Shui wrote:
> On Monday, 12 December 2016 at 22:35:22 UTC, Yuxuan Shui wrote:
>> On Monday, 12 December 2016 at 22:13:59 UTC, Ali Çehreli wrote:
>>> On 12/12/2016 02:08 PM, Yuxuan Shui wrote:
>>> > [...]
>>> wrote:
>>> >> [...]
>>> Error.bypassedException
>>> >> [...]
>>> mechanism,
>>> >> [...]
>>> Error."
>>> >> [...]
>>> Exception,
>>> >> [...]
>>> otherwise
>>> >> [...]
>>> original
>>> >> [...]
>>> is the Error.
>>> > [...]
>>> Exception to
>>> > [...]
>>>
>>> Currently yes. Now this line in my versatile :o) program:
>>>
>>> if (n >= errorIndex) {
>>>
>>> Two Errors are chained:
>>>
>>> Caught
>>> TestError: 3
>>> TestError: 4
>>>
>>> However, there is the following ongoing thread claiming that it was a wrong decision:
>>>
>>> http://forum.dlang.org/post/o2n347$2i1g$1@digitalmars.com
>>>
>>> > [...]
>>>
>>> From what I could graps from that much of documentation, yes, it seems to be a bug.
>>
>> I did some testing and bypassedException is null in 2.072.1, but is not null in 2.070.2
>>
>>>
>>> Ali
>
> The unwind process seem to stop one level too early, causing language_specific_data to be different, causing __dmd_personality_v0 to not chain exception into .bypassException.
OK. I think I figured it out. catch(Error x) won't catch TestException, so TestException 0,1,2 is not handled at main(). However TestError 3 (and TestExcepotion 4 which is chained to it) is handled at main(). And dmd won't put Throwables that are handled at different places together.
This behavior seems reasonable. So maybe this is actually a bug is LDC?
|
Copyright © 1999-2021 by the D Language Foundation