May 31, 2012
On 31.05.2012 13:06, deadalnix wrote:
> Le 31/05/2012 04:17, Walter Bright a écrit :
>> On 5/30/2012 8:05 AM, Steven Schveighoffer wrote:
>>> I'd classify errors/exceptions into three categories:
>>>
>>> 1. corruption/segfault -- not recoverable under any reasonable
>>> circumstances.
>>> Special cases exist (such as a custom paging mechanism).
>>> 2. program invariant errors (i.e. assert errors) -- Recovery is not
>>> defined by
>>> the runtime, so you must do it manually. Any decision the runtime
>>> makes will be
>>> arbitrary, and could be wrong.
>>> 3. try/catch exceptions -- these are planned for and *expected* to
>>> occur because
>>> the program cannot control it's environment. e.g. EOF when none was
>>> expected.
>>
>>
>> A recoverable exception is NOT a logic bug in your program, which is why
>> it is recoverable.
>>
>> If there is recovery possible from a particular assert error, then you
>> are using asserts incorrectly. Assert errors occur because your program
>> has entered an unanticipated, invalid state. There's no such thing as
>> knowing how to put it back into a valid state, because you don't know
>> where it went wrong and how much is corrupted, etc.
>
> A failure in database component should prevent me from close a network
> connection properly in an unrelated part of the program.
>
> This is called failing gracefully. And this highly recommended, and you
> KNOW that the system will fail at some point.

Exactly. + The point I tried to argue but it was apparently lost:
doing stack unwinding and cleanup on most Errors (some Errors like stack overflow might not recoverable) is the best thing to do.

Because crashing is easy ( hek catch(Error) abort(42); ), but not calling scope/destructors lays awful burden on programmer to do graceful clean up. The it's granted that nobody will ever bother doing it.

The fun boys of "crush immediately" should just call special runtime hook:
crashOnError(true);

Or the make it the default, but do _allow_ proper stack unwinding (= usual cleanup) after call to crashOnError(false).


-- 
Dmitry Olshansky
May 31, 2012
On Thursday, 31 May 2012 at 10:22:04 UTC, Dmitry Olshansky wrote:
> Or the make it the default, but do _allow_ proper stack unwinding (= usual cleanup) after call to crashOnError(false).

This would render nothrow useless, at least if the current semantics of it (throwing Errors is acceptable) are kept.

David
May 31, 2012
On 31.05.2012 20:30, David Nadlinger wrote:
> On Thursday, 31 May 2012 at 10:22:04 UTC, Dmitry Olshansky wrote:
>> Or the make it the default, but do _allow_ proper stack unwinding (=
>> usual cleanup) after call to crashOnError(false).
>
> This would render nothrow useless, at least if the current semantics of
> it (throwing Errors is acceptable) are kept.
>
> David

What are benefits of nothrow.
Aside from probably saving on codegen and documenting intent ?

-- 
Dmitry Olshansky
May 31, 2012
On 5/31/2012 2:06 AM, deadalnix wrote:
> A failure in database component should prevent me from close a network
> connection properly in an unrelated part of the program.

It *is* related if the process space is shared. The correct way to do what you're proposing is to make each component a separate process. Then, you are guaranteed that the failure of one component is separable, and restartable.


> This is called failing gracefully. And this highly recommended, and you KNOW
> that the system will fail at some point.

In a shared memory space, you have no guarantees whatsoever that the failure in the component is not a failure in the rest of the program. You cannot tell if it is related or not.
May 31, 2012
On 5/31/2012 12:40 AM, Jens Mueller wrote:
> How do I do a graceful shutdown if finally and scope is not guaranteed
> to be executed? Assuming onAssertError, etc. is of no use because I need
> to perform different shutdowns due to having different cases or if I
> defined my own Error, let's say for some device.

There's no way to guarantee a graceful shutdown.

No way.

If you must have such, then the way to do it is to divide your application into separate processes that communicate via interprocess communication, then when one component fails the rest of your app can restart it or do what's necessary, as the rest is not in an invalid state.

May 31, 2012
Walter Bright wrote:
> On 5/31/2012 12:40 AM, Jens Mueller wrote:
> >How do I do a graceful shutdown if finally and scope is not guaranteed to be executed? Assuming onAssertError, etc. is of no use because I need to perform different shutdowns due to having different cases or if I defined my own Error, let's say for some device.
> 
> There's no way to guarantee a graceful shutdown.
> 
> No way.
> 
> If you must have such, then the way to do it is to divide your application into separate processes that communicate via interprocess communication, then when one component fails the rest of your app can restart it or do what's necessary, as the rest is not in an invalid state.

Okay, let's assume I have separate processes maybe even processes on
different machines. In one process I get an error. Let's say I want to
trigger the other process that it restarts the process or just logs the
event whatever makes sense.
How do I do this if it not guaranteed that finally/scope blocks are
being executed?

I don't need a guarantee that the shutdown will work in each and every case. All I need is the possibility to perform a more graceful shutdown.

Jens
May 31, 2012
On May 31, 2012, at 1:05 PM, Jens Mueller <jens.k.mueller@gmx.de> wrote:

> Walter Bright wrote:
>> On 5/31/2012 12:40 AM, Jens Mueller wrote:
>>> How do I do a graceful shutdown if finally and scope is not guaranteed to be executed? Assuming onAssertError, etc. is of no use because I need to perform different shutdowns due to having different cases or if I defined my own Error, let's say for some device.
>> 
>> There's no way to guarantee a graceful shutdown.
>> 
>> No way.
>> 
>> If you must have such, then the way to do it is to divide your application into separate processes that communicate via interprocess communication, then when one component fails the rest of your app can restart it or do what's necessary, as the rest is not in an invalid state.
> 
> Okay, let's assume I have separate processes maybe even processes on
> different machines. In one process I get an error. Let's say I want to
> trigger the other process that it restarts the process or just logs the
> event whatever makes sense.
> How do I do this if it not guaranteed that finally/scope blocks are
> being executed?
> 
> I don't need a guarantee that the shutdown will work in each and every case. All I need is the possibility to perform a more graceful shutdown.

You pretty much need a local process monitor. This is needed anyway, since not every failure may throw. Say SIGBUS on Posix, for example.
June 01, 2012
On 5/31/2012 1:05 PM, Jens Mueller wrote:
> Okay, let's assume I have separate processes maybe even processes on
> different machines. In one process I get an error. Let's say I want to
> trigger the other process that it restarts the process or just logs the
> event whatever makes sense.
> How do I do this if it not guaranteed that finally/scope blocks are
> being executed?


Presumably the operating system provides a means to tell when a process is no longer running as part of its inter-process communication api.
June 01, 2012
On 5/31/2012 2:23 AM, Lars T. Kyllingstad wrote:
> On Thursday, 31 May 2012 at 02:18:22 UTC, Walter Bright wrote:
>> A recoverable exception is NOT a logic bug in your program, which is why it is
>> recoverable.
>>
>> If there is recovery possible from a particular assert error, then you are
>> using asserts incorrectly.
>
> I think this is a key point. Asserts are there to verify and debug program
> logic, they are not part of the logic itself. They are a useful tool for the
> programmer, nothing more. Specifically, asserts are NOT an error handling
> mechanism!

Right. And I'd like to amplify that the asserts are also there to detect program faults hopefully before damage is done.

If a program must continue even after it has failed, then you have a WRONGLY designed system.

It is extremely important to understand this point if you are implementing any sort of critical software.
June 01, 2012
On 5/31/2012 3:22 AM, Dmitry Olshansky wrote:
> On 31.05.2012 13:06, deadalnix wrote:
>> This is called failing gracefully. And this highly recommended, and you
>> KNOW that the system will fail at some point.
>
> Exactly. + The point I tried to argue but it was apparently lost:
> doing stack unwinding and cleanup on most Errors (some Errors like stack
> overflow might not recoverable) is the best thing to do.

This is all based on the assumption that the program is still in a valid state after an assert fail, and so any code executed after that and the data it relies on is in a workable state.

This is a completely wrong assumption.

It might be ok if the program is not critical and has no control over important things like delivering insulin, executing million dollar trades, or adjusting the coolant levels in a nuclear reactor.

If the code controls anything that matters, then it is not the best thing to do, not at all.

The right thing to do is to take the shortest path to stopping the program. A critical system would be monitoring those programs, and will restart them if they so fail, or will engage the backup system.

[When I worked on flight critical airplane systems, the only acceptable response for a self-detected fault was to IMMEDIATELY stop the system, physically DISENGAGE it from the flight controls, and inform the pilot.]