scope(exit) and scope(failure) on Errors

Jonathan M Davis via Digitalmars-d digitalmars-d at puremagic.com
Mon Apr 25 07:04:04 PDT 2016


On Monday, April 25, 2016 11:42:33 Shachar Shemesh via Digitalmars-d wrote:
> There is a problem with scope(exit) and scope(failure) running when
> Error types exceptions are thrown. It throws the program into code paths
> that are really not healthy.
>
> Imagine, for example, code handling linked lists. We do manipulations on
> linked lists, and put a scope(exit) that clears stuff up.
>
> Now imagine that somewhere inside, we have an assert that makes sure
> that everything is still in order. If it's not, then an AsserError is
> thrown, which derive from Error. The scope(exit) runs, but since things
> are not where they should be (hence the assert), we segfault. All the
> useful stuff that the assert was supposed to provide us is now gone,
> replaced by cleanup code that had no business running under those
> circumstances.
>
> Even when not harmful, this is, often, useless. Even if the cleanup
> proceeds correctly, what is the sense of cleaning up when the program is
> in serious trouble?
>
> The above is not categorically always true. In Weka, for example, we are
> using exceptions derived from Error to force all fibers of a certain
> logical component to exit. It is useful that these exceptions are not
> caught. In those cases, there are some types of cleanups that we do want
> to take place, but not others.
>
> Some way to control this would be appreciated.

The language does not guaranteed that scope(exit) statements, scope(failure)
statements, and destructors will be run when an Error is thrown, but neither
does it guarantee that they won't be. There have been arguments about it in
the past with Walter holding that they shouldn't be run when an Error is
thrown, because it's worse to run them than not when you're in an invalid
state (which you are by definition if an Error is thrown), whereas others
have argued that it's better to try and do as much cleanup as you can while
you're shutting down from an Error. For better or worse, the result is that
while the language does not guarantee that they aren't run when an Error is
thrown, the current implementation does run them in most cases (though there
are cases where it literally can't - like when nothrow is involved). And the
language provides no way to control whether they will get run on Errors.  It
depends entirely on the current implementation.

So, if you want to guarantee that scope(failure), scope(exit), and
destructors get run, you'll need to use an Exception of some kind, not an
Error, and if you want to guarantee that they don't get run, you'll need to
call a C function like exit or abort to forcibly kill the application.

- Jonathan M Davis



More information about the Digitalmars-d mailing list