Scope failure is not preventing application crush in case of uncaught exceptions

Jonathan M Davis newsgroup.d at jmdavisprog.com
Sun Dec 17 09:56:25 UTC 2017


On Sunday, December 17, 2017 09:32:53 codephantom via Digitalmars-d-learn 
wrote:
> On Sunday, 17 December 2017 at 08:26:03 UTC, Jonathan M Davis
>
> wrote:
> > assert(0) does indeed turn into a HLT instruction in -release
> > mode (as does any assertion that's known to be false at compile
> > time). It's a special case intended for marking code that's
> > supposed to be unreachable. Without -release, failed assertions
> > throw AssertErrors, so they're Errors not Exceptions, though I
> > think that scope statements currently catch and then rethrow
> > Throwable rather than Exception, which is why AssertErrors
> > would be affected.
> >
> > - Jonathan M Davis
>
> It's a little confusing, because Andrei's book says that
> scope(failure) guarantees statement will be executed, if and only
> if the current scope is exited by throwing an 'exception'.
>
> One could *mistakingly* take that as meaning, throwing an object
> rooted in the 'Exception' subclass of Throwable.
>
> Of course assert actually throws an exception too, but it's a
> special kind of exception rooted in the 'Error' subclass of
> Throwable.
>
> Perhaps, to be clearer, Andrei's book should have said:
> scope(failure) guarantees statement will be executed, if and only
> if the current scope is exited by throwing an object that
> inherits from type Throwable. That would include, objects rooted
> in the 'Exception' subclass, as well as objects rooted in 'Error'
> subclass.
>
> In which case, there's no bug in that code. It's doing what it's
> meant to be doing.

Well, exception vs Exception can be confusing, but there is actually no
guarantee whatsoever spec-wise that scope statements work with Errors - the
same goes for any other clean-up code (such as destructors or finally
blocks). Some stuff like nothrow functions make it impossible, and Walter
has been adamant that trying to recover from an Error is an incredibly bad
idea and that programs in general are far better off exiting on an Error
than trying to do any recovery from it (since by definition, when an Error
is thrown, the program is in a buggy and unknown state). Given Walter's
stance on it, I'm honestly a bit surprised that Error is a Throwable rather
than being designed to just immediately kill the program right then an
there, though under _rare_ circumstances, when you know exactly what you're
doing aand catch the Error pretty much at the point it was thrown, you can
get away with it for certain types of Errors like OutOfMemoryError.

However, at some point a while back, someone went into druntime and made it
so that destructors, scope statements, and finally blocks run as much as
possible when Errors are thrown - which isn't always but is a lot of the
time. So, on some level, right now, clean-up code does get run when an Error
is thrown, but it's not guaranteed and can't be guaranteed. Given Walter's
stance on it, I'm surprised that druntime has never been changed so that it
only does clean-up on Exceptions, but for now at least, we have a bit of a
halfway mess with how Errors are handled.

Basically, code shouldn't be relying on Errors either triggering or not
triggering clean-up code such as scope statements. They are only guaranteed
to run when an Exception is thrown and may or may not run when any other
kind of Throwable is thrown.

- Jonathan M Davis



More information about the Digitalmars-d-learn mailing list