[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: GError (Re: [Gnu-arch-users] "librifying" libarch)
From: |
Tom Lord |
Subject: |
Re: GError (Re: [Gnu-arch-users] "librifying" libarch) |
Date: |
Mon, 20 Oct 2003 18:00:38 -0700 (PDT) |
> From: Andrew Suffield <address@hidden>
> On Mon, Oct 20, 2003 at 01:58:32PM -0700, Tom Lord wrote:
> > Heck, there's a much simpler solution that's just
> > as good as domain+code:
> > typedef char * arch_error_t;
> This is a fragile ABI.
That's crazy-talk, man.
Short answer: the whole point of the error_t definition I described is
to trick the linker into allocating a unique address-per-error.
Linkers don't (in general) know how to do that for integer constants
or enums. The GError foo works around the same linker limitation by
performing a run-time allocation of a quark and replacing the error_t
type with a three-field structure.
Wouldn't it be nice if I could write foo.c:
enum error_codes includes
{
foo_err_machine_caught_fire,
foo_err_sysadmin_is_a_jerk,
}
and you could write bar.c:
enum error_codes includes
{
bar_err_comet_impact,
bar_err_gravitational_constant_changed,
}
and we could separately compile and link those together and wind up
with four distinct values for a variable of type `enum error_codes'
in "baz.c"?
But we can't do that. GError says (in part) "Ok, then do some
run-time initialization" and my error_t says "Ok, well, the linker can
come pretty close by allocating addresses for global data rather than
enum values."
The only lossage of the error_t technique compared to errno-style
integers is that error values aren't going to be densely-packed small
integers (which, formally, errno doesn't guarantee but it's a
reasonable presumption) -- but the trade-off in error_t is that
separately developed code can be linked together, each part bringing
it's own error_t values to the table.
The only lossage of the error_t technique compared to GError-style
handling is that error values aren't guaranteed to be a densely-packed
near-the-origin subset of the cartesian 2d plane -- but the trade-off
for that is that separately developed code can be linked together
without imposing a need for run-time initialization of error domains
and without a tediously tiresome interface to manipulating error
valuess.
> The pointer values are not portable between different processes, so
> you'll have to use the string values for IPC.
You've really deep-ended here.
No, if you wanted to exchange error codes, you wouldn't use
string-values for IPC - not in the way you presume. For many
protocols, you would probably want to include the string in messages.
(I'd be fine with a rule that says an error string used to initialize
an error_t value should contain only graphical characters and blanks.)
By way of illustration, classic text-based IETF protocols tend to be
based on something more complicated than and quite different from mere
error codes: they tend to use "response classes" + "error messages":
550 sdfljksdflsdjfsd: No such file OR directory.
^ ^
| |
response class error message
There's no error code in site there. The response class tells a
reader what kinds of response/reaction make sense. The message can be
forwarded to a user to give them a clue. But in the application
generating that message, many quite distinct "error codes" might
result in that same message: the client is not expected to be looking
for error codes, just response classes.
If you wanted to, in the error_t world, you could adopt a practice
which is the moral equivalent of:
550 (782344) No such file OR directory.
^ ^ ^
| | |
| error id error message
| (the address of
| the error string,
| usually)
|
response class
(optional, I guess)
and, if your protocol involves a subset of "standard error codes"
then:
550 ($1) No such file OR directory.
^ ^ ^
| | |
| error id error message
| (a standard encoding
| for this error)
|
|
response class
(optional, I guess)
and leave it up to your marshalling/unmarshalling code to puzzle out
what $1 refers to. This assumes that the recipient has some use for
the error code as distinct from the response class.
There's a very tiny subset of IPC in which it would make sense (say,
via a shared-memory region) to pass an integer errno value with no
marshalling/unmarshalling steps: processes related by fork (but with
no execs). And, guess what, my error_t works perfectly fine in that
case (for error codes present in the ancestor process) but GError
doesn't.
-t