View mode: basic / threaded / horizontal-split · Log in · Help
April 13, 2005
Re: OT Re: recoverable and unrecoverable errors or exceptions
"zwang" <nehzgnaw@gmail.com> wrote in message 
news:d3i61c$p7r$1@digitaldaemon.com...
> Matthew wrote:
>> [NOTE: GVIM's never had any kind of crash, or any other bug that 
>> I've ever used. It's great! (Although I wish I could find out how 
>> to get it to remember the last frame size, so I don't have to 
>> resize it every time)]
>>
> [snip]
>
> I wrote the following lines in $VIM/_vimrc to set up the window 
> size:
>
> winpos 0 0
> set lines=53
> set columns=166
>
> This is of course not a remember-the-last-frame-size solution, but 
> you
> might find it useful.

You're now officialy my best friend. :-)

Many thanks
April 13, 2005
Re: recoverable and unrecoverable errors or exceptions
>>But why would it be mandatory to shut down? If the core of the app 
>>is able to disable the plugin without shutting down, I'd say 
>>that's better (assuming, of course, that internal consistency can 
>>be ensured, which it can be in many cases, and can't be in many 
>>other cases; if it is not clear whether the app is in a consistent 
>>state, I agree shutting down completely is the best thing to do)
> 
> Alas, this is quite wrong and misses the point, although you do hint 
> at it. If the plug-in has violated its design, then any further 
> action performed by it or by any other part of the process is, in 
> principle, indeterminate and in outside the bounds of correct 
> behaviour. (Now, of course it is true that in many cases you can 
> carry on for a while, even a long while, but you run a non-zero risk 
> of ending in a nasty crash.)

Well, what you said also misses the point.. In principle, any action 
performed by a plug-in (or core) is indeterminate and whatever, it 
doesn't matter whether it has already produced a CP error or not. I fail 
to see what the big difference is between

assert(a!==null)

and

if (a is null)
    throw new IllegalArgumentException()

They both prevent the code that follows from running in the case where 
the supplied parameter is null, so you can't run it with invalid 
parameters, which is the whole purpose of those two statements.

Why is it so hard for you to admit that it is possible to have CP errors 
in code that cannot corrupt your app? I mean, if you give a plugin what 
is basically a read-only view of your data, it shouldn't be able to 
corrupt it. Sure it can, if it wants to, but that has nothing to do with 
CP, exceptions, errors or whatever.


> It is only 
> the case when a contract violation has occured, because only that is 
> a signal from the code's designer to the code's user (or rather the 
> runtime) that the plug-in is now invalid.

That's true. However, if I have a plugin that displays tooltips on some 
objects, I totally don't care if it encountered a CP violation or not, 
if it works, great, if it doesn't, too bad, no tooltips anymore in this 
session, I'll restart when I want to. But I really don't see a case for 
forcing the app, which otherwise works perfectly, to shut down.

I mean, if you don't trust your plugins go ahead and abort. But if you 
take measures to prevent the plugins from corrupting your data in the 
first place (like a read-only view), and are able to disable them in 
runtime, and they're not critical, what's the point?

You act as if code was written like

int thrownCP=0;

void someFunc()
{
   if (thrownCP) {
       // delete all files
       // overwrite all memory, except this function
       // try to launch all US nukes
   } else {
       if (something) {
           thrownCP=1;
           throw new CPError();
       }
       // do normal stuff
   }
}


> So, looking back at your para "If the code of the app is able to 
> disable the plugin without shutting down" applies to Exceptions (and 
> Exhaustions), whereas "if it is not clear whether the app is in a 
> consistent state, I agree shutting down completely is the best thing 
> to do" applies to Errors. These two things hold, of course, since 
> they are the definitions of Exceptions and Errors.

Well, who are you to decide that a CP error means an inconsistent state? 
Sure, it does in many cases, but not necessarily always. All I'm saying 
is that one should have a choice.


> CP violations are never tolerated, which means they get fixed _very_ 
> quickly.

Great, I just don't think everybody should be forced to work that way.


>>>>I mean, when I do something like inspect a value in a debugger, 
>>>>and the value is 150MB and the debugger runs out of memory, I 
>>>>don't want it to stop, just because it can't show me a var (which 
>>>>can just as easily manifest as an assertion error or whatever)...
>>>
>>>Out of memory is not an error, it's an exception, so that's just 
>>>not an issue.
>>
>>Like I said, out of memory can just as well manifest itself later 
>>as a broken contract or whatever.
> 
> 
> No, it cannot.

Sure it can:

int[] allocIfYouCan(int size)
{
    try {
        return new int[size];
    } catch (OutOfMemory ignored) {
        return null;
    }
}

void doSomething(int[] arr)
{
   assert(arr!==null);
}

doSomething(allocIfYouCan(10000000));

Obviously, allocIfYouCan() is not a good idea, but it can still happen.


> Dead wrong. Since 'parts' of the application share an address space, 
> a faulty part of an application is the very definition of the whole 
> application being faulty!
> 
> This is a crucial point, and a sine qua non for discussions on this 
> topic.
> 
> [snip]
> 
> But other languages that don't have pointers are just as dead in the 
> water. If you've a comms server written in Java - I know, I know, 
> but let's assumefor pedagogical purposes that you might - and a 
> plug-in violates its contract, then it can still do anything, like 
> kill threads, write out security information to the console, email 
> James Gosling a nasty letter, delete a crucial file, corrupt a 
> database.

Bah, this is just ridiculous. It can kill threads only if it was written 
to kill threads. If that is the case, no CP will help you. Same goes for 
everything else. A CP violation doesn't somehow magically transform the 
code into something that sends out email..


>  [snip]
> So (hopefully) you see that it is impossible to ever state
> (with even practical certainty) that "a faulty part of the
> application should not be taken as if the whole application
> is faulty".

No, I don't.. There are parts and there are parts. You're saying that 
even the tiniest error (but only if it was specified in a contract) 
should abort the app, I'm just saying that in some cases it's possible 
for that to be overreacting.


>>OK, it is obviously desired in some cases, so I agree it should be 
>>supported by the language, BUT, none of the built-in exceptions 
>>should then be unrecoverable.
> 
> Well again, I get the feeling that you think I've implied that a 
> wide range of things should be unrecoverable. I have not, and 
> perhaps I should say so explicitly now: AFAIK, only contract 
> violations should be Errors (i.e. unrecoverable), since only they 
> are a message from the author(s) of the code to say when it's become 
> invalid. 

How has the code become invalid exactly? The code doesn't change when it 
violates a contract.

For another example, let's say you have a DB-handling class with an 
invariant that the connection is always open to the DB (and that is a 
totally normal invariant). If you reboot the DB server, which is better 
- to kill all applications that use such class out there, or for them to 
reconnect?


> Only the author can know. Not the users of the libraries,
> not the users of any programs, not you or me, not even the designer 
> of the language can make that assertion.

Yup, and the author should have the option of using D's CP constructs 
without making his app die on every single error that happens.


xs0
April 13, 2005
Re: recoverable and unrecoverable errors or exceptions
"Ben Hinkle" <bhinkle@mathworks.com> wrote in message
news:d3f1nh$rj4$1@digitaldaemon.com...
> I'm looking into the Error/Exception situation in phobos and previous
posts
> by Walter and others generally argued that Exceptions are recoverable and
> Errors are not. I believe there isn't an application-independent
definition
> ...

Ben,

There is a lot of stuff in this thread, and quite understandly so, as this
is a somewhat touchy subject.

What the exact hierarchy should look like (C#, Java, etc.), I don't really
care about. I suppose it is the same for the vast majority of people out
there: they will use whatever is available, as long as it meets their needs.
Below is what I believe an error-handling design should address. I
unfortunetaly do not have time to dwelve in each point for very long, but I
doubt anyone would disagree with them. (And let me know if you do!)

The error-handling design:
- shall allow recoverability from normal exceptional cases...
... without checking every line for a return code. Any throw-catch design
has this.

- shall allow specifying a common exit procedure wheter an exception occured
or not
A try-catch-finally construct allows this.

- shall allow the ability to programatically analyze exceptions
It is important that the exception-handling code be able to look at the
exception. It should be able to print out an error message, display
something in the logs, send a SNMP alarm, do some correlation, send it
through a socket, etc. Some of this is achieved by simply catching
exceptions of a specific type, and some is not (for instance, the
human-readable error message). This leads to this first axiom:
*Every throwable object in the system should implement a basic interface*
(or derive from a base class).
This must be so for every library, every method, every class in the system.
*Allowing just any objects to be thrown specifically violates this.*

- shall allow all possible exceptional cases to be caught
This is more or less a sub-point of the above. It may be important for
reporting purposes that all possible errors be caught and reported. This can
be allowed with a catch(...) statement, but honestly, after (...) has been
caught, what can you possibly do with it? This is one of the most stupid
'features' of C++. I usually report: "Unkown exception caught". There is
then a 50% chance that I will find the root cause if I am in the lab and 0%
if it hapenned on a customer's system. (More on debugging later.) So, this
comes back to the point above that all exceptions should derive the same
interface/base class with (at least) a method to get a human readable error
message.
Note: some have argued that throwing an object would allow the application
to crash hard. Whereas I am not sure I understand why anyone would want to
do this (they haven't worked with critical systems for sure), not catching
an error (or rethrowing it) will lead to the same result.

- shall allow for checked and unchecked exceptions
Depending where you come from, I guess you can be all for checked
exceptions, or all against it. The truth of the matter is that both are
necessary in given circumstances.
Checked exceptions are exceptions that clients should be *explicitly* made
aware of and should deal with (if only to rethow it ). I know, I know, this
can be abused and lead to a lot of code simply rethrowing exceptions. It is
true that client code often cannot recover if the callee was not able to. No
matter, these exceptions are useful in certain circumstances.
To mitigate abuses, the default "Exception" class should probably be
unchecked (and not the other way around, like was done in Java).
Methods should list (as per their definitions) all checked exceptions they
throw and compilers should enforce that no other checked could be thrown.

- the language/default library shall define most (all) of its exceptions as
unchecked
In other words, it should assume the application logic ensures error-free
operation. For instance, an array list throwing IndexNotFoundExceptions
should not force clients to catch it.

- shall allow exceptions to be cascaded
In some situations, cascading exceptions is the best way to convey what
happened exactly. Also, it allows midware to specify aggregate exceptions
(that could have many causes) and let clients get to the exact root cause if
they so desire (most probably for error reporting). Cascading is usually
done by adding a parameter to the constructor and adding a getter to the
base exception class/interface:
this(..., Exception causedBy = null);
Exception causedBy();

- shall help debugging as much as possible
This is probably the most important point and can't be stressed enough. An
error-handling scheme that allows me to know exactly where the error
occured, by who the function was called (stack trace) and what were the
parameters, even when the error happened only once in the field is an
incredible blessing. It is great being able to tell a customer: "we know
what the problem is and a patch will be ready for you tomorrow". Even when
the root problem is an obscure race condition that never occured in your
gazillion tests in the lab. This saves a lot of people's asses and makes the
programmer's job a lot more enjoyable (and a hell of a lot less stressful
when you work with critical systems). You may think I exagerate, but I
don't... (speaking from experience here). And bugs are a reality in software
development, even in critical systems. No matter how good or witty you are.
More than anything else stack tracing leads to trustable code and rapid
development. Java does this well enough, but I understand that it may not be
possible to extract all the run-time information available to a JVM in
compiled code like D (and C++). However, every efforts should be made toward
that goal. For instance, if it is possible, at a performance cost, to have
stack traces, etc. available in the exception, I believe it should be made
available. In debug mode only perhaps, but I would let the programmer decide
if he still wants that info in production code. Performance is only one
factor in production code, but customers are often a lot more interested in
stability. If having stack traces costs 10% in performance but allows me to
iron out hard to find bugs in a day vs a week (or never), I'd chose the 10%
performance cost every time. Buying hardware 10% faster is cheaper than
paying a programmer (me!) finding hard race-conditions bugs. I am no
compiler writer though, so I don't know exactly what that would entail.

Hoping I am not forgetting anything...


BTW, thanks for all your hard work on D. I can honestly say D is the most
exciting thing I have come across in a looonnnngggg time. I spent all (last)
weekend checking it out, and I couldn't get to sleep... Went to bed at 5 or
6 AM every morning to the dismay of my SO... I am now tired as hell, but
very, very excited. Anyway, I am about to send a few bugs and glitches here
and there (and some suggestions perhaps). D has a few rough edges (like
exception-handling in fact), but I will program in D in my spare time from
now on. Got a project up my sleeve, and I believe I found a language to
grace it with!  ;)

Max
April 13, 2005
Re: recoverable and unrecoverable errors or exceptions
Hmmm... just glancing over this, I have to wonder.  Is there more than one interpretation of "CP" at work here?  I see some talk of what sounds like contract programming violations, and other talk of what could pass as co-processor errors or code page faults, or what-ever.  Maybe a little clarification is in order... then again, maybe I'm mistaken.

TZ

"xs0" <xs0@xs0.com> wrote in message news:d3itaa$1dtc$1@digitaldaemon.com...
> >>But why would it be mandatory to shut down? If the core of the app
> >>is able to disable the plugin without shutting down, I'd say
> >>that's better (assuming, of course, that internal consistency can
> >>be ensured, which it can be in many cases, and can't be in many
> >>other cases; if it is not clear whether the app is in a consistent
> >>state, I agree shutting down completely is the best thing to do)
> >
> > Alas, this is quite wrong and misses the point, although you do hint
> > at it. If the plug-in has violated its design, then any further
> > action performed by it or by any other part of the process is, in
> > principle, indeterminate and in outside the bounds of correct
> > behaviour. (Now, of course it is true that in many cases you can
> > carry on for a while, even a long while, but you run a non-zero risk
> > of ending in a nasty crash.)
>
> Well, what you said also misses the point.. In principle, any action
> performed by a plug-in (or core) is indeterminate and whatever, it
> doesn't matter whether it has already produced a CP error or not. I fail
> to see what the big difference is between
>
> assert(a!==null)
>
> and
>
> if (a is null)
>      throw new IllegalArgumentException()
>
> They both prevent the code that follows from running in the case where
> the supplied parameter is null, so you can't run it with invalid
> parameters, which is the whole purpose of those two statements.
>
> Why is it so hard for you to admit that it is possible to have CP errors
> in code that cannot corrupt your app? I mean, if you give a plugin what
> is basically a read-only view of your data, it shouldn't be able to
> corrupt it. Sure it can, if it wants to, but that has nothing to do with
> CP, exceptions, errors or whatever.
>
>
> > It is only
> > the case when a contract violation has occured, because only that is
> > a signal from the code's designer to the code's user (or rather the
> > runtime) that the plug-in is now invalid.
>
> That's true. However, if I have a plugin that displays tooltips on some
> objects, I totally don't care if it encountered a CP violation or not,
> if it works, great, if it doesn't, too bad, no tooltips anymore in this
> session, I'll restart when I want to. But I really don't see a case for
> forcing the app, which otherwise works perfectly, to shut down.
>
> I mean, if you don't trust your plugins go ahead and abort. But if you
> take measures to prevent the plugins from corrupting your data in the
> first place (like a read-only view), and are able to disable them in
> runtime, and they're not critical, what's the point?
>
> You act as if code was written like
>
> int thrownCP=0;
>
> void someFunc()
> {
>     if (thrownCP) {
>         // delete all files
>         // overwrite all memory, except this function
>         // try to launch all US nukes
>     } else {
>         if (something) {
>             thrownCP=1;
>             throw new CPError();
>         }
>         // do normal stuff
>     }
> }
>
>
> > So, looking back at your para "If the code of the app is able to
> > disable the plugin without shutting down" applies to Exceptions (and
> > Exhaustions), whereas "if it is not clear whether the app is in a
> > consistent state, I agree shutting down completely is the best thing
> > to do" applies to Errors. These two things hold, of course, since
> > they are the definitions of Exceptions and Errors.
>
> Well, who are you to decide that a CP error means an inconsistent state?
> Sure, it does in many cases, but not necessarily always. All I'm saying
> is that one should have a choice.
>
*snip*
April 13, 2005
Re: recoverable and unrecoverable errors or exceptions
comments inline

"Maxime Larose" <mlarose@broadsoft.com> wrote in message 
news:d3j3m2$1jsu$1@digitaldaemon.com...
>
> "Ben Hinkle" <bhinkle@mathworks.com> wrote in message
> news:d3f1nh$rj4$1@digitaldaemon.com...
>> I'm looking into the Error/Exception situation in phobos and previous
> posts
>> by Walter and others generally argued that Exceptions are recoverable and
>> Errors are not. I believe there isn't an application-independent
> definition
>> ...
>
> Ben,
>
> There is a lot of stuff in this thread, and quite understandly so, as this
> is a somewhat touchy subject.
>
> What the exact hierarchy should look like (C#, Java, etc.), I don't really
> care about. I suppose it is the same for the vast majority of people out
> there: they will use whatever is available, as long as it meets their 
> needs.
> Below is what I believe an error-handling design should address. I
> unfortunetaly do not have time to dwelve in each point for very long, but 
> I
> doubt anyone would disagree with them. (And let me know if you do!)
>
> The error-handling design:
> - shall allow recoverability from normal exceptional cases...
> ... without checking every line for a return code. Any throw-catch design
> has this.
>
> - shall allow specifying a common exit procedure wheter an exception 
> occured
> or not
> A try-catch-finally construct allows this.
>
> - shall allow the ability to programatically analyze exceptions
> It is important that the exception-handling code be able to look at the
> exception. It should be able to print out an error message, display
> something in the logs, send a SNMP alarm, do some correlation, send it
> through a socket, etc. Some of this is achieved by simply catching
> exceptions of a specific type, and some is not (for instance, the
> human-readable error message). This leads to this first axiom:
> *Every throwable object in the system should implement a basic interface*
> (or derive from a base class).
> This must be so for every library, every method, every class in the 
> system.
> *Allowing just any objects to be thrown specifically violates this.*

Why does having a base class of Object violate this? It has two useful 
methods: toString() and print(). To me that's what I would want in an 
exception base class. It would be nice to have methods for getting or 
printing a stack trace like Java and .Net but I'm not too worried about that 
and besides it wouldn't show up in D for a while (if it does show up it can 
be an interface). Is there something in particular that you'd like to see in 
the exception tree base class that isn't in Object?

> - shall allow all possible exceptional cases to be caught
> This is more or less a sub-point of the above. It may be important for
> reporting purposes that all possible errors be caught and reported. This 
> can
> be allowed with a catch(...) statement, but honestly, after (...) has been
> caught, what can you possibly do with it? This is one of the most stupid
> 'features' of C++. I usually report: "Unkown exception caught". There is
> then a 50% chance that I will find the root cause if I am in the lab and 
> 0%
> if it hapenned on a customer's system. (More on debugging later.) So, this
> comes back to the point above that all exceptions should derive the same
> interface/base class with (at least) a method to get a human readable 
> error
> message.
> Note: some have argued that throwing an object would allow the application
> to crash hard. Whereas I am not sure I understand why anyone would want to
> do this (they haven't worked with critical systems for sure), not catching
> an error (or rethrowing it) will lead to the same result.

D doesn't have catch(...). Instead one can catch(Object obj) and query obj. 
Technically the doc says you can catch without supplying a variable and it 
will catch everything and swallow the exception. Hopefully the compiler will 
warn if someone does that because that seems like an extreme catch.

> - shall allow for checked and unchecked exceptions
> Depending where you come from, I guess you can be all for checked
> exceptions, or all against it. The truth of the matter is that both are
> necessary in given circumstances.
> Checked exceptions are exceptions that clients should be *explicitly* made
> aware of and should deal with (if only to rethow it ). I know, I know, 
> this
> can be abused and lead to a lot of code simply rethrowing exceptions. It 
> is
> true that client code often cannot recover if the callee was not able to. 
> No
> matter, these exceptions are useful in certain circumstances.
> To mitigate abuses, the default "Exception" class should probably be
> unchecked (and not the other way around, like was done in Java).
> Methods should list (as per their definitions) all checked exceptions they
> throw and compilers should enforce that no other checked could be thrown.

I think there are archived threads about checked/unchecked exceptions. 
Walter didn't seem very keen on them but that might be because of a problem 
with Java's approach and maybe you are right that a slightly different 
approach would make them more attractive to Walter. Do you have a set of 
checked exceptions in mind?

> - the language/default library shall define most (all) of its exceptions 
> as
> unchecked
> In other words, it should assume the application logic ensures error-free
> operation. For instance, an array list throwing IndexNotFoundExceptions
> should not force clients to catch it.

agreed.

> - shall allow exceptions to be cascaded
> In some situations, cascading exceptions is the best way to convey what
> happened exactly. Also, it allows midware to specify aggregate exceptions
> (that could have many causes) and let clients get to the exact root cause 
> if
> they so desire (most probably for error reporting). Cascading is usually
> done by adding a parameter to the constructor and adding a getter to the
> base exception class/interface:
> this(..., Exception causedBy = null);
> Exception causedBy();

agreed. There have been recent (and probably achived, too) threads about 
this kind of thing and using it more often. For example Regan had a nice 
idea about cascading a SystemError to supply platform-specific error 
information and I've been looking at the various "foo not supported" 
exceptions in phobos with an eye towards cascading a NotSupportedException.

> - shall help debugging as much as possible
> This is probably the most important point and can't be stressed enough. An
> error-handling scheme that allows me to know exactly where the error
> occured, by who the function was called (stack trace) and what were the
> parameters, even when the error happened only once in the field is an
> incredible blessing. It is great being able to tell a customer: "we know
> what the problem is and a patch will be ready for you tomorrow". Even when
> the root problem is an obscure race condition that never occured in your
> gazillion tests in the lab. This saves a lot of people's asses and makes 
> the
> programmer's job a lot more enjoyable (and a hell of a lot less stressful
> when you work with critical systems). You may think I exagerate, but I
> don't... (speaking from experience here). And bugs are a reality in 
> software
> development, even in critical systems. No matter how good or witty you 
> are.
> More than anything else stack tracing leads to trustable code and rapid
> development. Java does this well enough, but I understand that it may not 
> be
> possible to extract all the run-time information available to a JVM in
> compiled code like D (and C++). However, every efforts should be made 
> toward
> that goal. For instance, if it is possible, at a performance cost, to have
> stack traces, etc. available in the exception, I believe it should be made
> available. In debug mode only perhaps, but I would let the programmer 
> decide
> if he still wants that info in production code. Performance is only one
> factor in production code, but customers are often a lot more interested 
> in
> stability. If having stack traces costs 10% in performance but allows me 
> to
> iron out hard to find bugs in a day vs a week (or never), I'd chose the 
> 10%
> performance cost every time. Buying hardware 10% faster is cheaper than
> paying a programmer (me!) finding hard race-conditions bugs. I am no
> compiler writer though, so I don't know exactly what that would entail.

Agreed that stack traces are very very useful - especially when a report 
comes in from the field that is not reproducible. If anyone knows of 
implementations or knows how to implement a "get the stack trace" function 
I'm sure it would be appreciated. I'm guessing it is compiler dependent, 
though. I know something exists since MATLAB does it for its C code and of 
course Java and .Net do it.

> Hoping I am not forgetting anything...

Thanks for the thoughtful post. Hearing fresh voices is very important.

> BTW, thanks for all your hard work on D. I can honestly say D is the most
> exciting thing I have come across in a looonnnngggg time. I spent all 
> (last)
> weekend checking it out, and I couldn't get to sleep... Went to bed at 5 
> or
> 6 AM every morning to the dismay of my SO... I am now tired as hell, but
> very, very excited. Anyway, I am about to send a few bugs and glitches 
> here
> and there (and some suggestions perhaps). D has a few rough edges (like
> exception-handling in fact), but I will program in D in my spare time from
> now on. Got a project up my sleeve, and I believe I found a language to
> grace it with!  ;)

cool. welcome!
April 13, 2005
Re: recoverable and unrecoverable errors or exceptions
Your points about throwing Objects are well noted. I didn't realize that the
toString and print functions would solve most of the problems I mentionned.
I still believe throwing a specific class (or interface) is better in the
case more stuff creeps in (like the stack traces). I mean, that's the whole
idea behind specializing (a class) in the first place right? In fact, the
main idea behind OO inheritance in general. Why would an Object be
throwable, when you can have a specialized Throwable class (or whatever)
that offers specialized services (like take a snapshot of the stack trace at
construction). IMO, it is better to make these kinds of
used-all-over-the-place-and-then-some classes/constructs (exceptions,
strings, etc.) thinking well into the future. Obviously, not all future
cases can be thought of now. However, if you foresee a possible change and
if, all other things being equal, a design better accomodates the change
than another, why not use the better accomodating design?

You ask about examples using checked exceptions... Hmmm... I guess you could
say that checked exceptions are a very useful part of contract programming.
Checked exceptions are useful when the exceptional case is part of the
possible operation of a given function, but rare enough that you wouldn't
want checking the return result at every call. And/or when the exceptional
case completely changes your program flow. That is, you want to *assume*
things went a certain way, because they will indeed go that way 99% of the
time. However you don't want clients to simply forget to implement that
case, because it is a very possible case, one they should deal with. A side
benefit is that the code is easier to read/maintain as the human mind works
in terms of normal cases vs exceptional cases - even if the exceptional case
is "normal" for the program itself.

A contrived example: let's say you have part of a program that parses a file
with an arbitrary number of lines in it. One method parses a single line. It
is possible the line is malformed, but very unlikely. How should you define
that method?
1. You return a value saying if the line was successfully parsed or not.
Welcome back in the old days.
2. You throw an exception. Throwing an unchecked exception gives you no
garantee that the client will deal with the case. This is especially true if
the method is in a library. Good programmers read the docs, true?
The real solution in these cases is throwing a checked exception. Clients
will *have* to act upon it. In our cases, an error message could be
displayed that line n is malformed, and parsing continues/stops/whatever.
You have some assurance that the exception will not be caught three callers
up, said caller having absolutely no idea about what went wrong and having
no choice than to simply display the exception text as is.

Again, these checked exceptions are not for the the D core library nor any
default language constructs (at all?). At any rate, unchecked exceptions
should be the default. Checked ones are for applications and "higher"
libraries, to help code and maintain contracts between components.

Thanks,

Max



"Ben Hinkle" <bhinkle@mathworks.com> wrote in message
news:d3j9av$1oso$1@digitaldaemon.com...
> comments inline
>
> "Maxime Larose" <mlarose@broadsoft.com> wrote in message
> news:d3j3m2$1jsu$1@digitaldaemon.com...
> >
> > "Ben Hinkle" <bhinkle@mathworks.com> wrote in message
> > news:d3f1nh$rj4$1@digitaldaemon.com...
> >> I'm looking into the Error/Exception situation in phobos and previous
> > posts
> >> by Walter and others generally argued that Exceptions are recoverable
and
> >> Errors are not. I believe there isn't an application-independent
> > definition
> >> ...
> >
> > Ben,
> >
> > There is a lot of stuff in this thread, and quite understandly so, as
this
> > is a somewhat touchy subject.
> >
> > What the exact hierarchy should look like (C#, Java, etc.), I don't
really
> > care about. I suppose it is the same for the vast majority of people out
> > there: they will use whatever is available, as long as it meets their
> > needs.
> > Below is what I believe an error-handling design should address. I
> > unfortunetaly do not have time to dwelve in each point for very long,
but
> > I
> > doubt anyone would disagree with them. (And let me know if you do!)
> >
> > The error-handling design:
> > - shall allow recoverability from normal exceptional cases...
> > ... without checking every line for a return code. Any throw-catch
design
> > has this.
> >
> > - shall allow specifying a common exit procedure wheter an exception
> > occured
> > or not
> > A try-catch-finally construct allows this.
> >
> > - shall allow the ability to programatically analyze exceptions
> > It is important that the exception-handling code be able to look at the
> > exception. It should be able to print out an error message, display
> > something in the logs, send a SNMP alarm, do some correlation, send it
> > through a socket, etc. Some of this is achieved by simply catching
> > exceptions of a specific type, and some is not (for instance, the
> > human-readable error message). This leads to this first axiom:
> > *Every throwable object in the system should implement a basic
interface*
> > (or derive from a base class).
> > This must be so for every library, every method, every class in the
> > system.
> > *Allowing just any objects to be thrown specifically violates this.*
>
> Why does having a base class of Object violate this? It has two useful
> methods: toString() and print(). To me that's what I would want in an
> exception base class. It would be nice to have methods for getting or
> printing a stack trace like Java and .Net but I'm not too worried about
that
> and besides it wouldn't show up in D for a while (if it does show up it
can
> be an interface). Is there something in particular that you'd like to see
in
> the exception tree base class that isn't in Object?
>
> > - shall allow all possible exceptional cases to be caught
> > This is more or less a sub-point of the above. It may be important for
> > reporting purposes that all possible errors be caught and reported. This
> > can
> > be allowed with a catch(...) statement, but honestly, after (...) has
been
> > caught, what can you possibly do with it? This is one of the most stupid
> > 'features' of C++. I usually report: "Unkown exception caught". There is
> > then a 50% chance that I will find the root cause if I am in the lab and
> > 0%
> > if it hapenned on a customer's system. (More on debugging later.) So,
this
> > comes back to the point above that all exceptions should derive the same
> > interface/base class with (at least) a method to get a human readable
> > error
> > message.
> > Note: some have argued that throwing an object would allow the
application
> > to crash hard. Whereas I am not sure I understand why anyone would want
to
> > do this (they haven't worked with critical systems for sure), not
catching
> > an error (or rethrowing it) will lead to the same result.
>
> D doesn't have catch(...). Instead one can catch(Object obj) and query
obj.
> Technically the doc says you can catch without supplying a variable and it
> will catch everything and swallow the exception. Hopefully the compiler
will
> warn if someone does that because that seems like an extreme catch.
>
> > - shall allow for checked and unchecked exceptions
> > Depending where you come from, I guess you can be all for checked
> > exceptions, or all against it. The truth of the matter is that both are
> > necessary in given circumstances.
> > Checked exceptions are exceptions that clients should be *explicitly*
made
> > aware of and should deal with (if only to rethow it ). I know, I know,
> > this
> > can be abused and lead to a lot of code simply rethrowing exceptions. It
> > is
> > true that client code often cannot recover if the callee was not able
to.
> > No
> > matter, these exceptions are useful in certain circumstances.
> > To mitigate abuses, the default "Exception" class should probably be
> > unchecked (and not the other way around, like was done in Java).
> > Methods should list (as per their definitions) all checked exceptions
they
> > throw and compilers should enforce that no other checked could be
thrown.
>
> I think there are archived threads about checked/unchecked exceptions.
> Walter didn't seem very keen on them but that might be because of a
problem
> with Java's approach and maybe you are right that a slightly different
> approach would make them more attractive to Walter. Do you have a set of
> checked exceptions in mind?
>
> > - the language/default library shall define most (all) of its exceptions
> > as
> > unchecked
> > In other words, it should assume the application logic ensures
error-free
> > operation. For instance, an array list throwing IndexNotFoundExceptions
> > should not force clients to catch it.
>
> agreed.
>
> > - shall allow exceptions to be cascaded
> > In some situations, cascading exceptions is the best way to convey what
> > happened exactly. Also, it allows midware to specify aggregate
exceptions
> > (that could have many causes) and let clients get to the exact root
cause
> > if
> > they so desire (most probably for error reporting). Cascading is usually
> > done by adding a parameter to the constructor and adding a getter to the
> > base exception class/interface:
> > this(..., Exception causedBy = null);
> > Exception causedBy();
>
> agreed. There have been recent (and probably achived, too) threads about
> this kind of thing and using it more often. For example Regan had a nice
> idea about cascading a SystemError to supply platform-specific error
> information and I've been looking at the various "foo not supported"
> exceptions in phobos with an eye towards cascading a
NotSupportedException.
>
> > - shall help debugging as much as possible
> > This is probably the most important point and can't be stressed enough.
An
> > error-handling scheme that allows me to know exactly where the error
> > occured, by who the function was called (stack trace) and what were the
> > parameters, even when the error happened only once in the field is an
> > incredible blessing. It is great being able to tell a customer: "we know
> > what the problem is and a patch will be ready for you tomorrow". Even
when
> > the root problem is an obscure race condition that never occured in your
> > gazillion tests in the lab. This saves a lot of people's asses and makes
> > the
> > programmer's job a lot more enjoyable (and a hell of a lot less
stressful
> > when you work with critical systems). You may think I exagerate, but I
> > don't... (speaking from experience here). And bugs are a reality in
> > software
> > development, even in critical systems. No matter how good or witty you
> > are.
> > More than anything else stack tracing leads to trustable code and rapid
> > development. Java does this well enough, but I understand that it may
not
> > be
> > possible to extract all the run-time information available to a JVM in
> > compiled code like D (and C++). However, every efforts should be made
> > toward
> > that goal. For instance, if it is possible, at a performance cost, to
have
> > stack traces, etc. available in the exception, I believe it should be
made
> > available. In debug mode only perhaps, but I would let the programmer
> > decide
> > if he still wants that info in production code. Performance is only one
> > factor in production code, but customers are often a lot more interested
> > in
> > stability. If having stack traces costs 10% in performance but allows me
> > to
> > iron out hard to find bugs in a day vs a week (or never), I'd chose the
> > 10%
> > performance cost every time. Buying hardware 10% faster is cheaper than
> > paying a programmer (me!) finding hard race-conditions bugs. I am no
> > compiler writer though, so I don't know exactly what that would entail.
>
> Agreed that stack traces are very very useful - especially when a report
> comes in from the field that is not reproducible. If anyone knows of
> implementations or knows how to implement a "get the stack trace" function
> I'm sure it would be appreciated. I'm guessing it is compiler dependent,
> though. I know something exists since MATLAB does it for its C code and of
> course Java and .Net do it.
>
> > Hoping I am not forgetting anything...
>
> Thanks for the thoughtful post. Hearing fresh voices is very important.
>
> > BTW, thanks for all your hard work on D. I can honestly say D is the
most
> > exciting thing I have come across in a looonnnngggg time. I spent all
> > (last)
> > weekend checking it out, and I couldn't get to sleep... Went to bed at 5
> > or
> > 6 AM every morning to the dismay of my SO... I am now tired as hell, but
> > very, very excited. Anyway, I am about to send a few bugs and glitches
> > here
> > and there (and some suggestions perhaps). D has a few rough edges (like
> > exception-handling in fact), but I will program in D in my spare time
from
> > now on. Got a project up my sleeve, and I believe I found a language to
> > grace it with!  ;)
>
> cool. welcome!
>
>
April 13, 2005
Re: recoverable and unrecoverable errors or exceptions
In article <d3i4nm$o0r$1@digitaldaemon.com>, Matthew says...
>
>> One important point is that I'm not recommending the removal of 
>> the CP  violation, quite the opposite, but, I believe that the 
>> programmer should  be able to make the informed decision about 
>> whether it's terminal or not.
>
>Ok. My understanding of your position is that that decision is 
>rightly within the purview of the programmer of a component's client 
>code, whereas I'm saying that (at least in principle) it can only be 
>within the purview of the component's programmer.

At the risk of muddying the waters a bit.  I think one might reasonably argue
that violation of preconditions is recoverable while violation of postconditions
is not.  In the first case, the client could theoretically detect the error, fix
the parameters and call the function again, while in the second case the client
has been stuck in a bad application state and there's little he can do about it.
Might it make sense to separate these concerns rather than just throwing
AssertErrors in all cases?


Sean
April 13, 2005
Re: recoverable and unrecoverable errors or exceptions
In article <d3i5dn$oda$1@digitaldaemon.com>, Ben Hinkle says...
>
>Forcing shutdown is annoying. As long as you tell the user what happened and 
>how serious it could be who are we to quit their app? (though honestly I 
>hope we don't start this whole thread over again) In some sense for the user 
>it's like when Windows tells you at some point you have to reboot after an 
>install (well... not all installs but you know what I mean). Windows doesn't 
>pop up a dialog that says "Reboot?" that just has an OK button. Error 
>recovery should inform the user but let them decide what to do - or worst 
>case let the application developer decide.

The only instance where this seems reasonable to me is in kernel code, and in
that case I expect the programmer would avoid the use of asserts (in release
mode) if he wants to insure the code never halts.  In other cases my personal
preference is to terminate the application and use a process monitor to restart
it if necessary.


Sean
April 13, 2005
Re: recoverable and unrecoverable errors or exceptions
In article <d3j9av$1oso$1@digitaldaemon.com>, Ben Hinkle says...
>
>comments inline
>
>"Maxime Larose" <mlarose@broadsoft.com> wrote in message 
>news:d3j3m2$1jsu$1@digitaldaemon.com...
>>
>> - shall allow the ability to programatically analyze exceptions
>> It is important that the exception-handling code be able to look at the
>> exception. It should be able to print out an error message, display
>> something in the logs, send a SNMP alarm, do some correlation, send it
>> through a socket, etc. Some of this is achieved by simply catching
>> exceptions of a specific type, and some is not (for instance, the
>> human-readable error message). This leads to this first axiom:
>> *Every throwable object in the system should implement a basic interface*
>> (or derive from a base class).
>> This must be so for every library, every method, every class in the 
>> system.
>> *Allowing just any objects to be thrown specifically violates this.*
>
>Why does having a base class of Object violate this? It has two useful 
>methods: toString() and print(). To me that's what I would want in an 
>exception base class. It would be nice to have methods for getting or 
>printing a stack trace like Java and .Net but I'm not too worried about that 
>and besides it wouldn't show up in D for a while (if it does show up it can 
>be an interface). Is there something in particular that you'd like to see in 
>the exception tree base class that isn't in Object?

I think the Object base class violates this to some people because it violates
the "what the hell is this?" principle (which I just made up).  If an
application throws something that is not an exception (ie. that doesn't describe
itself in some way) then the client has no idea what the error was.  Sure I
could throw a ClientAccount, but what was the error that caused the problem in
the first place?  Printing the ClientAccount won't help anyone in determining
that.  It would make much more sense to wrap it in an Exception with a bit of
descriptive information.


Sean
April 13, 2005
Re: recoverable and unrecoverable errors or exceptions
In article <d3jd4b$1sb6$1@digitaldaemon.com>, Sean Kelly says...
>
>At the risk of muddying the waters a bit.  I think one might reasonably argue
>that violation of preconditions is recoverable while violation of postconditions
>is not.  In the first case, the client could theoretically detect the error, fix
>the parameters and call the function again, while in the second case the client
>has been stuck in a bad application state and there's little he can do about it.
>Might it make sense to separate these concerns rather than just throwing
>AssertErrors in all cases?

This has me wondering (and I'm posting this to remind myself to test it), if an
exception is thrown out of a public class method with a postcondition, is that
postcondition evaluated?  What if the postcondition has an assertion failure as
well?  Also, is the class invariant evaluated if an exception is thrown?  What
if that also has an assert failure?  I know that auto classes are not currently
handled properly if execution leaves scope because of a thrown exception, what
about these other cases where we could theoretically have two or more exceptions
in flight at the same time?

Note that I'm ignoring finally blocks as exceptions thrown there are ignored and
just cause them to complete early (this is an issue in itself and one might
argue that finally blocks could violate application integrity depending on
what's in them).


Sean
3 4 5 6 7 8 9 10 11
Top | Discussion index | About this forum | D home