[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [Gnu-arch-users] Nit
From: |
Robin Farine |
Subject: |
Re: [Gnu-arch-users] Nit |
Date: |
22 Oct 2003 14:49:55 +0200 |
User-agent: |
Gnus/5.09 (Gnus v5.9.0) Emacs/21.2 |
>>>>> "Tom" == Tom Lord <address@hidden> writes:
Tom> 1) the original motivation for all this: what kind of conding
Tom> conventions to decide on for libhackerlab and for a possible
Tom> librefacation of libarch.
OK, I almost forgot the original goal.
[non-local exits are a no-go when programming in a language without
descent built-in support]
Yeah, the net advantage of this kind of "feature" is a very good rate
of resources leakage in long-term applications.
Tom> One thing _missing_ from this thread, other than the intial chat
Tom> about GError, is disucssion about the _pattern_matching_ aspect of
Tom> error handling. GError offers us domain/code which didn't really
Tom> strike me as compelling.
Since the idea is to check for errors at the call site, I think like
Andrew that a simple integer is sufficient. The values can be split
in two sets, a range from 0 to K-1 for common errors and the remaining
K..2^N-1 for library specific errors. Again, since errors are checked
at the call site, the caller knows the library the failing function
belongs to and thus can translate library specific codes into text
messages (e.g. by calling a per-library function that maps codes to
messages).
This can be combined with an error logging mechanism to provide the
ability to follow a sequence of correlated error messages for
diagnostic purpose. The UDI project offers a nice solution: a status
code consists of a 32 bits value split in a 16 bits correlation
number, one bit to differentiate between common errors and UDI
meta-language (library|module|domain|...) specific errors, and a 15
bits field for the actual error code.
The idea is that whenever an error occurs and a message is logged, the
logging function receives a reference to the status code and, iff the
correlation number is 0, it assigns the next available correlation
number to the status code. Then, it logs the message along with the
correlation number. Non-logging code is allowed to change the error
code but not the correlation number (except when initializing a newly
declared status code variable).
[...]
>From a previous post:
Tom> bar (error_t * caller_err, ...)
Tom> {
Tom> error_t err = 0;
Tom> foo (&err, ...);
Tom> if (is_error_i_handle (err))
Tom> handle it;
Tom> else if (is_error_i_forward)
Tom> forward_error (caller_err, err);
Tom> else
Tom> invariant (!err);
Tom> }
Tom> (With the understanding that `forward_err', if passed a NULL first
Tom> argument, turns into an abort.)
If bar() is a generic usage library function then (1) it should not
decide by itself to just abort in presence of an error and (2) it
should not handle and hide most of the errors (cf. "screen saver" vs
"nuclear power plant" or "caching memory allocator" examples). So this
basically leaves us with:
bar (error_t * caller_err, ...)
{
error_t err = 0;
foo (&err, ...);
if (caller_err)
forward_error (caller_err, err);
else
abort();
}
But foo() also respects the error protocol so bar() can just pass
caller_err to foo(), and so on. Such functions only needs to check
error returned from nested calls in order to cleanup locally allocated
resource and propagate the error upwards. A generic usage pattern
would look like
bool error(error_t * err) { return err && err->code; }
bar (error_t * err, ...)
{
...
foo1 (err);
if (error (err))
goto foo1_cleanup;
foo2 (err);
if (error (err)) {
goto foo2_cleanup;
log_error (err, "libzebu::bar() failed to foo2");
}
ret = baz ();
if (ret == -1) {
if (err) {
set_error (err, BAZERR /* not bizarre! */);
log_error (err, "libzebu::bar(): foobar in baz");
goto baz_cleanup;
} else
abort();
}
...
goto success;
baz_cleanup:
...
foo2_cleanup:
...
success:
return ...;
}
On the other hand, if bar() is a top-level application function, then
it would probably not take an error argument but rather declare it
locally and check and handle errors returned from nested library calls
or just pass them 0.
I also think that "is_error_i_handle (err)" would not in practice be
very useful. You mentioned violation of abstractions barriers in a
previous post. For a caller to be able to know whether it is good for
him that a callee handles an error or not implies that the caller
knows about the internals of nested functions in the call path. This
seems unrealistic and to imply a violation of abstraction barriers.
--
rnf
- Re: [Gnu-arch-users] Re: [OT] Java is fun!, (continued)
- Re: [Gnu-arch-users] Re: [OT] Java is fun!, Tom Lord, 2003/10/22
- Re: [Gnu-arch-users] Re: [OT] Java is fun!, Tom Lord, 2003/10/22
- [Gnu-arch-users] Re: [OT] Java is fun!, zander, 2003/10/22
- Re: [Gnu-arch-users] Re: [OT] Java is fun!, Tom Lord, 2003/10/22
- Re: [Gnu-arch-users] Re: [OT] Java is fun!, Thomas Zander, 2003/10/23
- [Gnu-arch-users] Re: [OT] Java is fun!, Miles Bader, 2003/10/23
- Re: [Gnu-arch-users] Re: [OT] Java is fun!, Momchil Velikov, 2003/10/23
- Re: [Gnu-arch-users] Re: [OT] Java is fun!, Tom Lord, 2003/10/23
- [Gnu-arch-users] Re: [OT] Java is fun, zander, 2003/10/24
- Re: [Gnu-arch-users] Re: [OT] Java is fun!, Mark A. Flacy, 2003/10/24
- Re: [Gnu-arch-users] Nit,
Robin Farine <=
- Re: [Gnu-arch-users] Nit, Andrew Suffield, 2003/10/22
- Re: [Gnu-arch-users] Nit, Tom Lord, 2003/10/22
- Re: [Gnu-arch-users] Nit, David Brown, 2003/10/22
- Re: [Gnu-arch-users] Nit, Neal D. Becker, 2003/10/22
- Re: [Gnu-arch-users] Nit, Robin Farine, 2003/10/22
- error_t (was Re: [Gnu-arch-users] Nit), Tom Lord, 2003/10/22
- Re: error_t (was Re: [Gnu-arch-users] Nit), Robin Farine, 2003/10/23
- Re: error_t (was Re: [Gnu-arch-users] Nit), Tom Lord, 2003/10/23
- Re: [Gnu-arch-users] Nit, Andrew Suffield, 2003/10/23
- Re: [Gnu-arch-users] Nit, Tom Lord, 2003/10/23