View mode: basic / threaded / horizontal-split · Log in · Help
April 01, 2013
Re: DIP33: A standard exception hierarchy
On 04/01/2013 12:44 PM, Dmitry Olshansky wrote:> 01-Apr-2013 20:00, John 
Colvin пишет:

>> Therefore, you're better off not trying to cleanup if program state
>> could be invalid.
>
> Data is corrupted no matter if you just fail to write it in a consistent
> state (sudden assertion in some 3-rd party library) or corrupt
> accidentally by bad write (during cleanup on corrupted RAM).

The failed assertion may be the moment when the program detects that 
something is wrong. A safe program should stop doing anything else.

> Therefore you should always try to orderly cleanup but do not rely on it
> to actually work at all circumstances (thus backups, commits/save
> points, watchdogs and whatnot).

A safe program must first guarantee that that cleanup is harmless, which 
is not possible when the program is in an invalid state. Imagine sending 
almost infinite number of "cleanup" commands to a device that can harm 
people who are around it.

Ali
April 01, 2013
Re: DIP33: A standard exception hierarchy - why out-of-memory is not recoverable
On 4/1/2013 4:08 AM, Lars T. Kyllingstad wrote:
> It's time to clean up this mess.

About out-of-memory errors
--------------------------

These are considered non-recoverable exceptions for the following reasons:

1. I've almost never seen a program that could successfully recover from out of 
memory errors, even ones that purport to.

2. Much effort is expended trying to make them recoverable, yet it doesn't work, 
primarily because the recovery paths are never tested.

3. There are an awful lot of instances where memory is allocated - almost as 
many as allocating stack space. (Running out of stack space doesn't even throw 
an Error exception, the program is just unceremoniously aborted.)

4. Making it recoverable means that pure functions now have side effects. 
Function purity, rather than a major feature of D, would become a little-used 
sideshow of marginal utility.

5. Although a bad practice, destructors in the unwinding process can also 
allocate memory, causing double-fault issues.

6. Memory allocation happens a lot. This means that very few function 
hierarchies could be marked 'nothrow'. This throws a lot of valuable 
optimizations under the bus.

7. With the multiple gigs of memory available these days, if your program runs 
out of memory, it's a good sign there is something seriously wrong with it (such 
as a persistent memory leak).

8. If you must recover from specific out of memory possibilities, you can still 
use malloc() or some other allocation scheme that does not rely on the GC.
April 01, 2013
Re: DIP33: A standard exception hierarchy - finally blocks not executed for Errors
On 4/1/2013 4:08 AM, Lars T. Kyllingstad wrote:
> It's time to clean up this mess.


As for why finally blocks are not executed for Error exceptions, the idea is to 
minimize cases where the original error would now cause an abort during the 
unwinding process. Catching an Error is useful for things like:

1. throw the whole plugin away and restart it
2. produce a log of what happened before aborting
3. engage the backup before aborting
4. alert the operator that the system has failed and why before aborting

Unwinding is not necessary for these, and can even get in the way by causing 
other failures and aborting the program by attempting cleanups when the code is 
in an invalid state.
April 01, 2013
Re: DIP33: A standard exception hierarchy
02-Apr-2013 00:34, Ali Çehreli пишет:
> On 04/01/2013 12:44 PM, Dmitry Olshansky wrote:> 01-Apr-2013 20:00, John
> Colvin пишет:
>
>  >> Therefore, you're better off not trying to cleanup if program state
>  >> could be invalid.
>  >
>  > Data is corrupted no matter if you just fail to write it in a consistent
>  > state (sudden assertion in some 3-rd party library) or corrupt
>  > accidentally by bad write (during cleanup on corrupted RAM).
>
> The failed assertion may be the moment when the program detects that
> something is wrong. A safe program should stop doing anything else.

And that's precisely the interesting moment. It should stop but the 
definition of "stop" really depends on many factors. Just pretending 
that calling abort is a panacea is totally wrong IMO.

BTW what do you exactly mean by "safe" program?

>  > Therefore you should always try to orderly cleanup but do not rely on it
>  > to actually work at all circumstances (thus backups, commits/save
>  > points, watchdogs and whatnot).
>
> A safe program must first guarantee that that cleanup is harmless, which
> is not possible when the program is in an invalid state.

There could a lot of ways to do that even in "illegal" state. Restore 
and conservative reconstruction of valid state is often possible (like 
restoring files on a faulty hard drive) with a help of certain tricks 
you can get high estimates of these actions to succeed.

Once you have resigned yourself to black and white - valid /invalid 
there is no way to go indeed.

> Imagine sending
> almost infinite number of "cleanup" commands to a device that can harm
> people who are around it.

These are far better off with built-in hardware fail-safe switches and 
redundant circuitry.

Just suddenly stopping the program in the control of a spinning blade 
that cuts through somebody's tissue is not good enough.

>
> Ali
>


-- 
Dmitry Olshansky
April 01, 2013
Re: DIP33: A standard exception hierarchy
On Mon, 01 Apr 2013 22:34:39 +0200, Ali Çehreli <acehreli@yahoo.com> wrote:

> A safe program must first guarantee that that cleanup is harmless, which  
> is not possible when the program is in an invalid state. Imagine sending  
> almost infinite number of "cleanup" commands to a device that can harm  
> people who are around it.

Of course. But the opposite is also the case - failure to turn off  
dangerous
hardware, or leaving hardware in a dangerous state when the program fails
is just as bad as putting it in an unknown state. The decision must be made
on a case-by-case basis.

I am reminded of Therac-25[1]. though the situation there was slightly
different, similar situations could arise from not turning off hardware.


[1]: http://en.wikipedia.org/wiki/Therac-25
-- 
Simen
April 01, 2013
Re: DIP33: A standard exception hierarchy
01-Apr-2013 23:46, Lars T. Kyllingstad пишет:
> On Monday, 1 April 2013 at 18:40:48 UTC, Dmitry Olshansky wrote:
>> 01-Apr-2013 15:08, Lars T. Kyllingstad пишет:
>>> It's time to clean up this mess.
>>>
>>> http://wiki.dlang.org/DIP33
>>
>> Overall neat.
>>
>> 1. Where to define this hierarchy.
>> Captain the obvious says std.exception, but can we fit all of them there?
>
> Some of them have to be in core.exception.  Personally, I think the rest
> of the base hierarchy should be in std.exception.  In fact, I think the
> "standard hierarchy" should be defined as "what's in core.exception and
> std.exception".
>
> If we identify cases where modules absolutely *must* extend these
> classes for extremely specific purposes, this can be done within the
> module.

Good. We are mostly on the same page here and later.

>
>> 2. ProcessException is IMHO a system exception. Plus some RTOses
>> systems may not have processes in the usaul POSIX sense. It needs some
>> thought.
>
> Well, I *don't* think ProcessException is a SystemException. :) And if
> druntime/Phobos is to be used on OSes that don't have processes, there
> are other adaptations that have to be made that are probably more
> fundamental.

Okay. I guess all of this goes to "Embedded D"/"D Lite" kind of spec.

Last thing - why separating ThreadException vs ProcessException and 
should they have some base class? Just asking to see the rationale 
behind it that is missing from DIP currently.

>
>> 4. A quiz as an extension of 3 - where a e.g. serial port exceptions
>> would fit in this hierarchy? Including Parity errors, data overrun etc.
>> Let's think a bit ahead and pick names wisely.
>> Maybe turn NetworkException --> Comm(unication)Exception, I dunno.
>
> Good question, I dunno either. :)  I agree we should think about it.
>
>
>> 5. Continuing the above - a failed call (in-system) of a general
>> purpose IPC library would be a ... SystemException? A network
>> exception? Should it matter to the user?
>
> Note that I am only saying that the standard exceptions should cover
> *most* error categories.  100% is not feasible, and we shouldn't even
> try.  This may be one of the exceptions (haha) to the rule.
>

Well, maybe we could just extend it later on. As it's easier to add then 
remove then let's deffer the hard ones :)

>> 6. I like ParseException. Wondering if could be generalized a bit - in
>> a sense it's a "bad format"/"malformed" exception. For instance
>> corrupt DB file reporting ParseException (= bad format) is rather wacky.
>
> I agree, and welcome all suggestions for better names.

>
>> 8. For IOExcpetion we might consider adding an indication on which
>> file handle the problem happened and/or if it's closed/invalid/"mostly
>> fine" that.
>
> Which form do you suggest that such an indicator should take?

That's the trick - I hoped somebody will just say "aha!" and add one :)

The internal handle is hard to represent other then ... some platform 
specific integer value. There goes generality... Other then this there 
is a potential to stomp on feet of higher-level abstraction on top of 
that handle.

That last bit makes me reconsider the idea. While I see some potential 
use for it I suspect it's too niche to fit in the general hierarchy.

> Bear in
> mind that it should be general enough to cover all, or at least most,
> kinds of I/O exceptions.

Adding a Kind that states one of:
out-of-data (read empty file)
illegalOp (reading closed file, writing read-only file/socket)
interrupted (operation was canceled by OS, connection forcibly closed, 
disk ejected etc.)
hardFault (OS reports hardware failure)

...
etc. shouldn't hurt. Need to think this through better, of course, and 
consult OSes manuals again.
-- 
Dmitry Olshansky
April 01, 2013
Re: DIP33: A standard exception hierarchy
On 4/1/2013 2:20 PM, Simen Kjærås wrote:
> I am reminded of Therac-25[1]. though the situation there was slightly
> different, similar situations could arise from not turning off hardware.

Relying on a program running correctly in order to avoid disaster is a terrible 
design. Even mathematically proving a program to be correct is in no way, shape, 
or form sufficient to deal with this.
April 01, 2013
Re: DIP33: A standard exception hierarchy
On Monday, April 01, 2013 21:33:22 Lars T. Kyllingstad wrote:
> My problem with subclasses is that they are a rather heavyweight
> addition to an API. If they bring no substance (such as extra
> data), I think they are best avoided.

Except that they're extremely valuable when you need to catch them. Being able 
to do something like

try
{
...
}
catch(FileNotFoundException fnfe)
{
//handling specific to missing files
}
catch(PermissionsDeniedException pde)
{
//handling specific to lack of permissions
}
catch(FileExceptionfe
{
//generic file handling error
}
catch(Exception e)
{
//generic error handling
}

can be very valuable. In general, I'd strongly suggest having subclasses for 
the various "Kind"s in addition to the kind field. That way, you have the 
specific exception types if you want to have separate catch blocks for different 
error types, and you have the kind field if you just want to catch the base 
exception.

If anything, exceptions are exactly the place where you want to have derived
classes with next to nothing in them, precisely because it's the type that the
catch mechanism uses to distinguish them.

- Jonathan M Davis
April 01, 2013
Re: DIP33: A standard exception hierarchy
On 04/01/2013 02:01 PM, Dmitry Olshansky wrote:> 02-Apr-2013 00:34, Ali 
Çehreli пишет:

>> The failed assertion may be the moment when the program detects that
>> something is wrong. A safe program should stop doing anything else.
>
> And that's precisely the interesting moment. It should stop but the
> definition of "stop" really depends on many factors. Just pretending
> that calling abort is a panacea is totally wrong IMO.
>
> BTW what do you exactly mean by "safe" program?

I meant a program that wants to produce correct results. I was indeed 
thinking about Therac-25 that Simen Kjærås mentioned. I agree that there 
must be hardware fail-safe switches as well but they could not protect 
people from every kind of software failure in that example.

Having said that, I can see the counter argument as well: We are in an 
inconsistent state, so trying to do something about it could be better 
than not running a cleanup code. But I also remember that an AssertError 
may be thrown by an assert() call, telling us that a programmer put it 
in there explicitly, meaning that the program cannot continue. If there 
was any chance of recovery, then the programmer could have thrown an 
Exception or remedy the situation right then.

Ali
April 01, 2013
Re: DIP33: A standard exception hierarchy
On Mon, 01 Apr 2013 18:26:22 -0400, Jonathan M Davis <jmdavisProg@gmx.com>  
wrote:

> On Monday, April 01, 2013 21:33:22 Lars T. Kyllingstad wrote:
>> My problem with subclasses is that they are a rather heavyweight
>> addition to an API. If they bring no substance (such as extra
>> data), I think they are best avoided.
>
> Except that they're extremely valuable when you need to catch them.  
> Being able
> to do something like
>
> try
> {
>  ...
> }
> catch(FileNotFoundException fnfe)
> {
>  //handling specific to missing files
> }
> catch(PermissionsDeniedException pde)
> {
>  //handling specific to lack of permissions
> }
> catch(FileExceptionfe
> {
>  //generic file handling error
> }
> catch(Exception e)
> {
>  //generic error handling
> }
>
> can be very valuable. In general, I'd strongly suggest having subclasses  
> for
> the various "Kind"s in addition to the kind field. That way, you have the
> specific exception types if you want to have separate catch blocks for  
> different
> error types, and you have the kind field if you just want to catch the  
> base
> exception.
>
> If anything, exceptions are exactly the place where you want to have  
> derived
> classes with next to nothing in them, precisely because it's the type  
> that the
> catch mechanism uses to distinguish them.

In general, this is not enough.  Imagine having an exception type for each  
errno number.  Someone may want that!

Note that there are two categories of code dealing with thrown exceptions:

1. whether to catch
2. what to do

Right now, we have the super-basic java/c++ model of matching the type for  
item 1.  D could be much better than that:

catch(SystemException e) if(e.errno == EBADF)
{
   ...
}

For item 2, once you have the caught exception, you have mechanisms to  
deal with the various fields of the exception.  So even without  
improvements to #1, you can rethrow the exception if it's not what you  
wanted.  Just the code isn't cleaner:

catch(SystemException e)
{
   if(e.errno != EBADF)
      throw e;
}

-Steve
1 2 3 4 5 6 7
Top | Discussion index | About this forum | D home