digitalmars.D.learn - chain of exceptions, next method
- kdevel (62/62) Aug 13 2022 Quote from `src/druntime/src`:
- =?UTF-8?Q?Ali_=c3=87ehreli?= (36/50) Aug 13 2022 This automatic "combining" of exceptions happens for cleanup code like
- Paul Backus (9/24) Aug 13 2022 To be precise, an exception thrown inside a 'finally' block gets
- Andrej Mitrovic (5/14) Sep 10 2022 I wish the compiler would rewrite scope(failure) to use chained
- kdevel (12/17) Mar 06 Ran into this issue with the following ordering bug:
- Jonathan M Davis (6/23) Mar 06 If anything, I think that it's been decided that chained exceptions were...
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
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 whena 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
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
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: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.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.
Sep 10 2022
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
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: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[...] 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