Exception chaining and collectException

H. S. Teoh via Digitalmars-d digitalmars-d at puremagic.com
Thu Aug 17 14:48:07 PDT 2017


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.


More information about the Digitalmars-d mailing list