September 13, 2014
On Friday, 12 September 2014 at 11:38:18 UTC, Andrej Mitrovic via Digitalmars-d wrote:
> On 9/12/14, Jakob Ovrum via Digitalmars-d <digitalmars-d@puremagic.com> wrote:
>> the chaining mechanism will
>> construct a self-referencing list that results in an infinite
>> loop when the chain is walked
>
> Can we amend the spec to say self-referencing is ok? Then we could
> make the default exception handler *stop* if it finds a
> self-referencing exception (e.g. for stack traces), and for custom
> user code which walks through exceptions it would either have to be
> fixed.
>
> We could also provide a helper function for walking through exceptions:
>
> try
> {
>     ...
> } catch (Exception ex)
> {
>     // some UFCS or object.d built-in method which
>     // stops walking when ".next is this"
>     foreach (caught; ex.walk)
>     {
>     }
> }
>
> Or does the problem have a bigger scope than just walking?

The exception chain would be unable to chain further exceptions. Each exception in the chain needs its own unique `next` pointer.

Also, the two links to the same exception could appear anywhere in the list. I think some sort of caching of exceptions already encountered would be required, which is a lot slower and more complex than the existing mechanism.
September 13, 2014
On Friday, 12 September 2014 at 12:47:46 UTC, Vladimir Panteleev
wrote:
> On Friday, 12 September 2014 at 03:37:10 UTC, Jakob Ovrum wrote:
>> I can think of a couple of ways to go:
>
>> 1) The most widely discussed path is to allocate exception instances statically, either in global memory or TLS. Currently, this has a few serious problems:
>
> Another problem with this is that you'll need to change every instance of "new FooException" to something else.

I don't think this is a big problem, `@nogc` will tell you where
the allocations are, and it's fairly easy to just grep and
replace. It's also worth noting that code using enforce et al.
could be updated automatically.

Further, you only need to do this if you want your library code
to be `@nogc`. Existing code using the GC-heap will keep working
(except for the `scope` thing I proposed...).
September 13, 2014
On Friday, 12 September 2014 at 16:33:50 UTC, Dmitry Olshansky wrote:
> Agreed.
>
> I think that the total amount of live (not garbage) exceptions on heap is small for any typical application. Thus just special casing the hell out of exception allocation in the GC (and compiler) is IMO perfectly satisfactory hack.

We can't use the GC as the whole point is to mark library code `@nogc`. It should work even if the user has ripped the GC out of druntime with a custom build.
September 13, 2014
On Friday, 12 September 2014 at 21:36:31 UTC, Johannes Pfau wrote:
> I think if we could avoid dynamic allocations for most exceptions
> completely that'd be better. IIRC some people said that exceptions are
> mainly slow because of memory allocation. So if we could avoid that,
> there are more benefits.

While we should ideally make the exception mechanism as fast as possible, it mustn't be a priority, lest we compromise more important parts of the design for the red herring that is performance.

If a program is slow because of exception handling it's not using exceptions correctly. It should replace that part of the code with a solution that uses error codes. This is the mantra that goes for all languages with exceptions that I know, except Python and maybe Java.

Also, we know the approximate size of exceptions and their allocation pattern. An efficient heap allocator could be designed to take advantage of this.

That's not to say I'm against any non-heap solution if we can think of something really good, but we should keep our priorities straight.

> I suggest looking at the C++ implementation. There's the throw-by-value
> catch-by-reference idiom. C++ must store/copy this exception somewhere,
> maybe they have a clever solution.
>
> (We basically need some fixed-size per thread memory where we can store
> the exception and stack trace info. But we need a fallback because of
> exception chaining or big exceptions.)

I think this is essentially global storage allocation. C++ does not do exception chaining so this is much more viable there.

Also, when we decide to use TLS instead of the mess that would be shared exceptions, we introduce a massive chunk of required data for each new thread in every application that depends on Phobos and/or other libraries using the new exception allocator.
September 13, 2014
13-Sep-2014 06:01, Jakob Ovrum пишет:
> On Friday, 12 September 2014 at 16:33:50 UTC, Dmitry Olshansky wrote:
>> Agreed.
>>
>> I think that the total amount of live (not garbage) exceptions on heap
>> is small for any typical application. Thus just special casing the
>> hell out of exception allocation in the GC (and compiler) is IMO
>> perfectly satisfactory hack.
>
> We can't use the GC as the whole point is to mark library code `@nogc`.
> It should work even if the user has ripped the GC out of druntime with a
> custom build.

Then call it "exception heap" or some such, and make sure it's somehow separate. It still means GC got to scan it.

-- 
Dmitry Olshansky
September 13, 2014
On Friday, 12 September 2014 at 21:31:45 UTC, Johannes Pfau wrote:
> Am Fri, 12 Sep 2014 12:59:22 +0000
> schrieb "Marc Schütz" <schuetzm@gmx.net>:
>
>> On Friday, 12 September 2014 at 03:37:10 UTC, Jakob Ovrum wrote:
>> >   1b) Exceptions constructed at compile-time which are then later referenced at runtime (as in the above snippet) must be immutable (the compiler enforces this), as this feature only supports allocation in global memory, not in TLS. This brings us to an unsolved bug in the exception mechanism - the ability to get a mutable reference to an immutable exception without using a cast:
>> 
>> Related: Last time I checked the runtime caches unwinding or stack trace information in the exception. It does this even for immutable exceptions...
>
> Yes, in order to avoid allocating a stack trace helper you need to cast
> the exception from its .init property, IIRC. There's some code in
> druntime which does that (the out-of-memory error handling code).

That's not what I mean, please see here:
http://forum.dlang.org/thread/ftakrucgtfcicfbkzwbs@forum.dlang.org#post-xmvzmufjywcsxviooivl:40forum.dlang.org
September 14, 2014
On Saturday, 13 September 2014 at 08:19:10 UTC, Marc Schütz wrote:
> On Friday, 12 September 2014 at 21:31:45 UTC, Johannes Pfau wrote:
>> Am Fri, 12 Sep 2014 12:59:22 +0000
>> schrieb "Marc Schütz" <schuetzm@gmx.net>:
>>> Related: Last time I checked the runtime caches unwinding or stack trace information in the exception. It does this even for immutable exceptions...
>>
>> Yes, in order to avoid allocating a stack trace helper you need to cast
>> the exception from its .init property, IIRC. There's some code in
>> druntime which does that (the out-of-memory error handling code).
>
> That's not what I mean, please see here:
> http://forum.dlang.org/thread/ftakrucgtfcicfbkzwbs@forum.dlang.org#post-xmvzmufjywcsxviooivl:40forum.dlang.org

Indeed the entire exception mechanism does not account for immutability at all which is not surprising considering it was implemented in the days of D1 and there's a lot of type erasure going on when druntime functions are called, but it does mean any sighting of a non-mutable exception anywhere is a big red flag until we overhaul exceptions to account for immutability.
September 19, 2014
I am obviously in favor of simply calling recurrent mutable exception chains illegal (probably even immutable ones until we fix const correctness of druntime exception handling).

Reason is simple : it doesn't require any changes in existing code and is exactly the way we already do it in Sociomantic :)

To make it reliable Exception chain may need to be updated to doubly-linked list to be able to efficiently verify that new exception is not already present in the chain. I don't see any costly overhead implications from that though.
September 19, 2014
On Friday, 19 September 2014 at 07:57:24 UTC, Dicebot wrote:
> I am obviously in favor of simply calling recurrent mutable exception chains illegal (probably even immutable ones until we fix const correctness of druntime exception handling).
>
> Reason is simple : it doesn't require any changes in existing code and is exactly the way we already do it in Sociomantic :)
>
> To make it reliable Exception chain may need to be updated to doubly-linked list to be able to efficiently verify that new exception is not already present in the chain. I don't see any costly overhead implications from that though.

That might be sufficient for a particular application like Sociomantic's, but it's not sufficient for library code in general. Such chains aren't logic errors and can easily occur in the wild.

The point of exception chaining is so exceptions can be thrown in destructors and such. In library code, these destructors don't know what exception is in flight, so they can only assume it could be any exception. If self-referencing chains were illegal and exceptions were statically allocated, then the conclusion is that these destructors can't throw anything after all, because that exception might already be in flight. As such, exception chaining would be completely useless.
September 19, 2014
On Friday, 19 September 2014 at 11:36:29 UTC, Jakob Ovrum wrote:
> That might be sufficient for a particular application like Sociomantic's, but it's not sufficient for library code in general. Such chains aren't logic errors and can easily occur in the wild.
>
> The point of exception chaining is so exceptions can be thrown in destructors and such. In library code, these destructors don't know what exception is in flight, so they can only assume it could be any exception. If self-referencing chains were illegal and exceptions were statically allocated, then the conclusion is that these destructors can't throw anything after all, because that exception might already be in flight. As such, exception chaining would be completely useless.

This is pretty much saying that anything should be able to throw anything. For me it sounds as flawed application - if recurrent chaining happens when handling destructor, most likely there is a fundamental programming error in application logic (some sort of cyclic dependency) and it should be pointed to and fixed.

Probably there is some convincing example of such legal code but I can't imagine it on my own.
1 2
Next ›   Last »