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