www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - chain of exceptions, next method

reply kdevel <kdevel vogtner.de> writes:
Quote from `src/druntime/src`:

```
     /**
      * Returns:
      * A reference to the _next error in the list. This is used 
when a new
      * $(D Throwable) is thrown from inside a $(D catch) block. 
The originally
      * caught $(D Exception) will be chained to the new $(D 
Throwable) via this
      * field.
      */
      property inout(Throwable) next()  safe inout return scope 
pure nothrow  nogc { return nextInChain; }

```

Testcode:

```
import std.stdio;
import std.exception;

private:

class E1 : Exception { mixin basicExceptionCtors; }
class E2 : Exception { mixin basicExceptionCtors; }

void foo ()
{
    try throw new E1 ("e1");
    catch (Exception e)
       throw new E2 ("e2");
}

void bar ()
{
    auto e = new E1 ("e1");
    e.next = new E2 ("e2");
    throw e;
}

void dumpall (Exception e)
{
    Throwable t = e;
    stderr.writeln ("dumpall");
    do
       stderr.writeln (t.msg);
    while ((t = t.next) !is null); // XXX: Why does !!(t = t.next) 
not compile?
}

public void main ()
{
    try foo ();
    catch (Exception e)
       dumpall (e);

    try bar ();
    catch (Exception e)
       dumpall (e);
}

$ dmd cetest
$ ./cetest
dumpall
e2
dumpall
e1
e2
```

Would have expected two chained Exceptions in both cases. Is it 
permitted to append exceptions from user code?
Aug 13 2022
parent reply =?UTF-8?Q?Ali_=c3=87ehreli?= <acehreli yahoo.com> writes:
On 8/13/22 15:59, kdevel wrote:
 Quote from `src/druntime/src`:

 ```
      /**
       * Returns:
       * A reference to the _next error in the list. This is used when 
a new
       * $(D Throwable) is thrown from inside a $(D catch) block. The
 originally
       * caught $(D Exception) will be chained to the new $(D Throwable)
 via this
       * field.
       */
       property inout(Throwable) next()  safe inout return scope pure
 nothrow  nogc { return nextInChain; }

 ```
This automatic "combining" of exceptions happens for cleanup code like scope(exit). (I remember bug(s) for scope(failure).): import std.stdio; void foo() { // Bug? Should work for scope(failure) as well. scope (exit) { bar(); } throw new Exception("from foo"); } void bar() { throw new Exception("from bar"); } void main() { try { foo(); } catch (Exception exc) { for (Throwable e = exc; e; e = e.next) { writeln(e.msg); } } } The output: from foo from bar You can do the same by calling chainTogether(). Here is an excerpt from an old experiment of mine: try { foo(); } catch (Throwable exc) { Throwable.chainTogether(exc, new Exception(" ... ")); throw exc; } Ali
Aug 13 2022
parent reply Paul Backus <snarwin gmail.com> writes:
On Sunday, 14 August 2022 at 02:07:05 UTC, Ali Çehreli wrote:
 This automatic "combining" of exceptions happens for cleanup 
 code like scope(exit). (I remember bug(s) for scope(failure).):
To be precise, an exception thrown inside a 'finally' block gets chained onto the previous exception, but an exception thrown inside a 'catch' block does not. scope(exit) and scope(failure) are just syntax sugar for 'finally' and 'catch', respectively. Relevant spec paragraph:
 If an exception is raised in the FinallyStatement and is not 
 caught before
 the original exception is caught, it is chained to the previous 
 exception via
 the next member of Throwable. Note that, in contrast to most 
 other
 programming languages, the new exception does not replace the 
 original
 exception. Instead, later exceptions are regarded as 
 'collateral damage'
 caused by the first exception. The original exception must be 
 caught, and
 this results in the capture of the entire chain.
Source: https://dlang.org/spec/statement.html#try-statement So, once an exception is caught, the chain ends, and any exception thrown after that begins a new chain.
Aug 13 2022
parent reply Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
On Sunday, 14 August 2022 at 02:30:43 UTC, Paul Backus wrote:
 On Sunday, 14 August 2022 at 02:07:05 UTC, Ali Çehreli wrote:
 This automatic "combining" of exceptions happens for cleanup 
 code like scope(exit). (I remember bug(s) for scope(failure).):
To be precise, an exception thrown inside a 'finally' block gets chained onto the previous exception, but an exception thrown inside a 'catch' block does not. scope(exit) and scope(failure) are just syntax sugar for 'finally' and 'catch', respectively.
I wish the compiler would rewrite scope(failure) to use chained exceptions. Otherwise any exceptions thrown within scope(failure) can end up losing information about what was the original exception that was thrown.
Sep 10 2022
parent reply kdevel <kdevel vogtner.de> writes:
On Saturday, 10 September 2022 at 08:48:39 UTC, Andrej Mitrovic 
wrote:
 [...]
 I wish the compiler would rewrite scope(failure) to use chained 
 exceptions. Otherwise any exceptions thrown within 
 scope(failure) can end up losing information about what was the 
 original exception that was thrown.
Ran into this issue with the following ordering bug: auto tmpfilename = fn.dup ~ ".XXXXXX\0"; int fd = mkstemp (tmpfilename.ptr); scope (failure) remove (tmpfilename); // bug: if (fd == -1) throw new Exception (strerror(errno).to!string); The error thrown was Failed to remove file ... Is there any work in progress to chain the exceptions in scope(failure)?
Mar 06
parent Jonathan M Davis <newsgroup.d jmdavisprog.com> writes:
On Wednesday, March 6, 2024 6:06:34 AM MST kdevel via Digitalmars-d-learn 
wrote:
 On Saturday, 10 September 2022 at 08:48:39 UTC, Andrej Mitrovic

 wrote:
 [...]
 I wish the compiler would rewrite scope(failure) to use chained
 exceptions. Otherwise any exceptions thrown within
 scope(failure) can end up losing information about what was the
 original exception that was thrown.
Ran into this issue with the following ordering bug: auto tmpfilename = fn.dup ~ ".XXXXXX\0"; int fd = mkstemp (tmpfilename.ptr); scope (failure) remove (tmpfilename); // bug: if (fd == -1) throw new Exception (strerror(errno).to!string); The error thrown was Failed to remove file ... Is there any work in progress to chain the exceptions in scope(failure)?
If anything, I think that it's been decided that chained exceptions were a mistake. So, if things go in any direction with them, it's likely to be towards removing them, not doing more to support them. - Jonathan M Davis
Mar 06