runtime hook for Crash on Error

Jonathan M Davis jmdavisProg at gmx.com
Tue Jun 5 08:44:10 PDT 2012


On Tuesday, June 05, 2012 13:57:14 Don Clugston wrote:
> On 05/06/12 09:07, Jonathan M Davis wrote:
> > On Tuesday, June 05, 2012 08:53:16 Don Clugston wrote:
> >> On 04/06/12 21:29, Steven Schveighoffer wrote:
> >>> On Mon, 04 Jun 2012 06:20:56 -0400, Don Clugston<dac at nospam.com>  wrote:
> >>>> 1. There exist cases where you cannot know why the assert failed.
> >>>> 2. Therefore you never know why an assert failed.
> >>>> 3. Therefore it is not safe to unwind the stack from a nothrow
> >>>> function.
> >>>> 
> >>>> Spot the fallacies.
> >>>> 
> >>>> The fallacy in moving from 2 to 3 is more serious than the one from 1
> >>>> to 2: this argument is not in any way dependent on the assert occuring
> >>>> in a nothrow function. Rather, it's an argument for not having
> >>>> AssertError at all.
> >>> 
> >>> I'm not sure that is the issue here at all. What I see is that the
> >>> unwinding of the stack is optional, based on the assumption that there's
> >>> no "right" answer.
> >>> 
> >>> However, there is an underlying driver for not unwinding the stack --
> >>> nothrow. If nothrow results in the compiler optimizing out whatever
> >>> hooks a function needs to properly unwind itself (my limited
> >>> understanding is that this helps performance), then there *is no
> >>> choice*, you can't properly unwind the stack.
> >>> 
> >>> -Steve
> >> 
> >> No, this whole issue started because the compiler currently does do
> >> unwinding whenever it can. And Walter claimed that's a bug, and it
> >> should be explicitly disabled.
> >> 
> >> It is, in my view, an absurd position. AFAIK not a single argument has
> >> been presented in favour of it. All arguments have been about "you
> >> should never unwind Errors".
> > 
> > It's quite clear that we cannot completely, correctly unwind the stack in
> > the face of Errors.
> 
> Well that's a motherhood statement. Obviously in the face of extreme
> memory corruption you can't guarantee *any* code is valid.
> The *main* reason why stack unwinding would not be possible is if
> nothrow intentionally omits stack unwinding code.

It's not possible precisely because of nothrow.

> > As such, no one should be relying on stack unwinding when an
> > Error is thrown.
> 
> This conclusion DOES NOT FOLLOW. And I am getting so sick of the number
> of times this fallacy has been repeated in this thread.
> 
> These kinds of generalizations are completely invalid in a systems
> programming language.

If nothrow prevents the stack from being correctly unwound, then no, you 
shouldn't be relying on stack unwinding when an Error is thrown, because it's 
_not_ going to work properly.

> > Regardless, I think that there are a number of people in this thread who
> > are mistaken in how recoverable they think Errors and/or segfaults are,
> > and they seem to be the ones pushing the hardest for full stack unwinding
> > on the theory that they could somehow ensure safe recovery and a clean
> > shutdown when an Error occurs, which is almost never possible, and
> > certainly isn't possible in the general case.
> > 
> > - Jonathan M Davis
> 
> Well I'm pushing it because I implemented it (on Windows).
> 
> I'm less knowledgeable about what happens on other systems, but know
> that on Windows, the whole system is far, far more robust than most
> people on this thread seem to think.
> 
> I can't see *any* problem with executing catch(Error) clauses. I cannot
> envisage a situation where that can cause a problem. I really cannot.

In many cases, it's probably fine, but if the program is in a bad enough state 
that an Error is thrown, then you can't know for sure that any particular such 
block will execute properly (memory corruption being the extreme case), and if 
it doesn't run correctly, then it could make things worse (e.g. writing 
invalid data to a file, corrupting that file). Also, if the stack is not unwound 
perfectly (as nothrow prevents), then the program's state will become 
increasingly invalid the farther that the program gets from the throw point, 
which will increase the chances of cleanup code functioning incorrectly, as 
any assumptions that they've made about the program state are increasingly 
likely to be wrong (as well as it being increasingly likely that the variables 
that they operate on no longer being valid).

A lot of it comes down to worst case vs typical case. In the typical case, the 
code causing the Error is isolated enough and the code doing the cleanup is 
self-contained enough that trying to unwind the stack as much as possible will 
result in more correct behavior than skipping it all. But in the worst case, 
you can't rely on running any code being safe, because the state of the 
program is very much invalid, in which case, it's better to kill the program 
ASAP. Walter seems to subscribe to the approach that it's best to assume the 
worst case (e.g. that an assertion failure indicates horrible memory 
corruption), and always have Errors function that way, whereas others 
subscribe to the approach that things are almost never that bad, so we should 
just assume that they aren't, since skipping all of that cleanup causes other 
problems.

And it's not that the error-handling system isn't robust, it's that if the 
program state is invalid, then you can't actually assume that _any_ of it's 
valid, no matter how well it's written, in which case, you _cannot_ know 
whether running the cleanup code is better or worse than skipping it. Odds are 
that it's just fine, but you have no such guarantee, because there's no way for 
the program to know how severe or isolated an Error is when it occurs. It just 
knows that something went horribly wrong.

- Jonathan M Davis


More information about the Digitalmars-d mailing list