gnu-arch-users
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Gnu-arch-users] Nit


From: Tom Lord
Subject: Re: [Gnu-arch-users] Nit
Date: Tue, 21 Oct 2003 19:49:53 -0700 (PDT)



    > From: Robin Farine <address@hidden>

    >>> The good thing with a library function raising an exception is that
    >>> while the call backtracks, intermediate callers that just ignore the
    >>> error won't hide it.

    >Tom> When you say "callers that just ignore the error" you mean callers
    >Tom> that don't put any code to check for the error, right?

    > Yes.
    > 
    >Tom> If so, no, that's the _bad_ thing about a library function raising an
    >Tom> exception:

    > I did not say that having an exception mechanism automatically
    > enforces good error handling design. Just like programming in an OO
    > language does not magically yield simple and beautiful designs. And it
    > does not prevent us to create bugs either. It is possible to do bad
    > thing with any tool, a fortiori, in a very difficult area like error
    > handling.

We've lost a little context here.  I don't disagree with anything
you've said so far.  I would agree that exception handling interfaces
are handy (a "tool for the toolbox").  I'd go further and say that, in
a sufficiently hairy application, I probably want more than one such
interface -- even if they are all isomorphic (yet disjoint,
non-interfering) -- and a separate, generic unwind-protection feature
(like Scheme's dynamic-wind) so that I can combine them all
coherently.  But hey, we're off in the stratosphere here -- back to
earth:

I'm trying to talk about three (somewhat unrelated) things at once.

1) the original motivation for all this:  what kind of conding
   conventions to decide on for libhackerlab and for a possible
   librefacation of libarch.

   One conclusion I've drawn from this thread is that the non-local
   exit property of exceptions are a no-go for this (I was previously
   considering it!)  Internally to these libraries, except in very
   limited and specific ways (as in the pseudo_process_exit_lonjmp
   facility I described) errors must be handled at the caller site.  C
   doesn't give us a handy way to handle "out of band" return values,
   hence, the emerging error_t mechanism.

   The reason that non-local exits are a no-go for general purpose
   error handling is that cients of the library, to be properly
   written, would have to use the non-local exit facility in such a
   manner that no non-local exits through the client code actually
   occur!  So, other than internally (like
   pseudo_process_exit_lonjmp), the error convention has to be error
   codes, not exceptions.


   One thing _missing_ from this thread, other than the intial chat
   about GError, is disucssion about the _pattern_matching_ aspect of
   error handling.  GError offers us domain/code which didn't really
   strike me as compelling.  My current error_t proposal essentially
   reduces that to just `code' (no domain).  Yet other systems, Java,
   the SRFI's I pointed miles at, many many other systems -- use a
   pattern matching system for errors based on inheritance among
   claseses of exceptions.  As we put the exceptions-vs-error-codes
   foo to bed, perhaps it would be interesting to next ask "what is
   the type structure of the set error values as pertains to pattern
   matching in handlers"?



2) a flaw in Java

   Java is promoted as a safe language.   It is not a safe language
   and the Java-fans contributing to this (while, certainly, helping
   me improve the error_t design) have indirectly pointed that out.

   People have been talking about Java on this list like it is an
   examplar of great language design ("mature software") and promoting
   Java coding conventions that exacerbate the safety problems ("don't
   just catch and retrhow errors").    

   This isn't, in my judgement, the kind of problem I could file a
   CERT advisery about.  It's _theoretically_ possible to use Java in
   ways that don't create exploitable holes -- it just takes an
   (apparently explicitly unpopular) discipline.  But the fact is that
   the Java folklore presented here, by fans of Java, makes
   exploitable holes likely to arise.  And the second fact is that a
   slightly different language design -- a more clu-like exception
   mechanism -- would close those particular potential holes.


3) Language and run-time system design "in general"

   I'm at least trying, perhaps quite unsuccesfully, to expose the
   kind of thinking one has to go through when designing a general
   purpose error processing mechanism ("In my opinion", as zander
   would have me say.)   I'm no Guy Steele, but I'm also not a slouch
   or inexperienced poser in this area.


In short: exceptions?  Nifty, gimme plenty.   What to use in my
libraries?  Error codes!   What people should use in Java to avoid
exploitable holes?  More discipline than they thought!   What's the
design space?  <no pithy summary>


    >     Tom> This works fine until, later, the implementation of B_fn is 
modified
    >     Tom> to also call D_fn.    Perhaps D_fn is a logging function that 
tries to
    >     Tom> send a message to the admin user.
    >     Tom> In making the change to B_fn, the programmer makes a mistake.   
He
    >     Tom> doesn't notice that D_fn can throw a no_such_user exception (if 
the
    >     Tom> admin account is missing) and just ignores that case.

    > Keep in mind that I am no expert at all, but let me try to sketch what
    > I would do with this example. At a glance, I see two subsystems. One that
    > deals with configurations and another that provides logging services,
    > so each deserves its own exception classes. [....]

Agreed.  The context of my burbling about B_fn and friends is simply
to, slowly and gently, point out that Java is not a safe language
unless programs are written with a discipline that, according to
Java-fans on this list, is positively discouraged.  The discouraged
discipline (or better, changes to the Java language) would all but
_force_ the use of separate exception classes in this instance.  But
Java as reportedly practiced, and as the langauge spec enforces,
respectively encourages and permits fatal mistakes in this area.

It looks, from evidence on this list, like the significance of the
`throws' clauses in method declarations has been widely misunderstood.


    > [long back and forth examples, ending up with my example of what
    >  a safe java call looks like]


    > This seems to indicate that you identify exceptions with return codes
    > since doing this is equivalent to passing by reference an error
    > argument to non pure functions and checking the returned
    > values. 

That's true.

    > As my above example attempts to show, exceptions provide a tool
    > an order of magnitude more powerful than return codes. Using
    > them correctly requires a different way of thinking to design
    > error handling mechanisms.

They don't provide a mechanism that's any more powerful than the
combination of error-codes and upward-only continuations.   Meanwhile,
by using error codes in a general purpose library, clients of that
library are required to explicitly rather than implicitly screw up.




    >     Tom> But there's no getting around it (not for cleanups,
    >     Tom> necessarily -- just to turn unanticipated exceptions into
    >     Tom> aborts rather than forwarding them to unsuspecting callers).

    > C++ offers exactly this by adding exception specifications to function
    > prototypes. It is not always desirable to to so, though. For instance,
    > the designer of a template class cannot in general know the exceptions
    > raised by the types specified as arguments during instantiation of the
    > template. I think Eiffel or Ada can restrict the exceptions raised by
    > generic type arguments, but in practice it is very hard to specify
    > stable APIs using this feature.

The problem for Java, as distinct from those other languages, is that
Java encourages the dynamic linking of untrusted code.


    >     Tom> It'd be nice to have short syntax for:

    >     Tom> a) abort on _any_ error in this call
    >     Tom> b) drop _all_ error codes from this call
    >     Tom> c) forward _all_ error codes from this call

    > Don't Java exception specifications or C++ (member) function
    > declarations provide exactly this functionality?

Sure, but:

        foo (0, ....);

is shorter syntax than:

        try {
           mumble.foo (...);
        } catch (Except e) {
           grumble.panic (...);
        }

and so forth.





reply via email to

[Prev in Thread] Current Thread [Next in Thread]