[Top][All Lists]
[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: |
Thu, 23 Oct 2003 09:37:47 -0700 (PDT) |
> From: Andrew Suffield <address@hidden>
> On Wed, Oct 22, 2003 at 11:58:08AM -0700, Tom Lord wrote:
>> That's why I think that the address of a string constant works out
>> better than densely-packed integers: the linker will give each error
>> (represented as a string constant) it's own address (in each
>> executable or process).
> But you sacrifice the possibility of passing errors between
> processes, and I can't see any reason why you do that - nothing in
> your scheme depends on the error values being randomly assigned in
> every process.
Ok, we can fix that now (and, strangely enough, I have a use for it).
Shades of GError follow. The general trick is not to require a
global namespace of integer error codes but to permit a global
namespace of pairs:
(domain, code)
where `domain' is a string that should be stable and have a unique md5
hash, code an integer allocated by the authority that stakes out that
domain name.
The portable number defining an error is 160 bits:
: md5 sum of domain (128 bits) : code (32 bits) :
If an error type has a NULL domain, a code can be assigned to it
on-demand but, in general the error type is not portable between
processes. (Or, rather, the process can make up a temporary domain
for itself and send and receive back these errors -- but other
processes won't automatically identify them with their own local error
types.)
Error parameters can be handled somewhat but not in the general case.
Something like this:
struct error_params_vtable;
typedef struct error_params_vtable;
struct error_type
{
/* short graphical-chars name for the error:
*/
char * name;
/* sentence fragment msg for error
*/
char * msg;
/* type description of parameters to this kind
* error.
*/
struct error_params_vtable * vtable;
/* optional name of the authority that allocated an error
* code for this error type.
*/
char * domain;
/* error code (within the domain) for this error
*/
t_uint32 code;
/* if is_proxy is not 0, then this is not the
* definitive struct error_type for this error_type.
*
* The fields name, msg, and domain are not authoritative
* for this error type. vtable is authoritative if not 0.
*/
int is_proxy;
/* if is_proxy, then proxy_for is either 0 or a pointer
* to the authoritative struct error_type for this error type.
*/
struct error_type * proxy_for;
/* if dom_cached, then domhash_hi and domhash_lo are
* an md5sum for the authoritative domain name.
*/
t_uint64 domhash_hi;
t_uint64 domhash_lo;
/* if not 0, a (non-portable) densely packed natural number
* unique to this error type (not the struct -- the actual
* error).
*/
t_uint domseq;
};
typedef struct error_type * error_type_t;
struct error
{
struct error_type * type;
void * params;
};
#define ERROR_TYPE_DECL(NAME, MSG, VT) \
error_type_t NAME { #NAME, #MSG, VT, 0, };
#define PORTABLE_ERROR_TYPE_DECL(NAME, MSG, DOM, COD) \
error_type_t NAME { #NAME, MSG, VT, DOM, COD, , 0 };
Ok, so, if you need an error code but don't have an integer allocated
from a central authority, you can declare it with:
ERROR_TYPE_DECL (err_rmn_crack, "socket to me?", rmn_vtable);
and if you _do_ have an authoritative protable error code
you can use:
#include "hackerlab/bugs/portable-errors.h"
PORTABLE_ERROR_TYPE_DECL (err_rmn_crack,
"socket to me?",
rmn_vtable,
HACKERLAB_ERROR,
HLERR_RMN_CRACK);
If an error has a domain of NULL, then it is _not_ a portable error
zcode. (It can be assigned a per-process error code on demand,
though.)
Checking the type of an error becomes more complicated:
error_is_type (type, err)
{
if (type->proxy_for)
type = type->proxy_for;
if (error->type->proxy_for)
error->type = error->type->proxy_for;
if (type->is_proxy
&& !error->type->is_proxy
same_dom_and_code (type, error->type))
{
type->proxy_for = error->type;
type = type->proxy_for;
}
if (error->type->is_proxy
&& !type->is_proxy
same_dom_and_code (type, error->type))
{
error->type->proxy_for = type;
error->type = type;
}
if (err->type == type)
return 1;
else
return same_dom_and_code (type, error->type);
}
error_t should really be opaque. I think the client view of its
internal structure is mostly just:
char * error_name (err);
char * error_msg (err);
int error_code (&domhi, &domlo, &code, err);
error_type_t error_type (err);
(but people need to use error_is_type or error_types_equal
rather than == to compare error types).
For convenience, we can add:
t_uint error_type_seq (error_type)
Return a (non-portable) densely packed
integer that is unique to this error type.
As for error parameters: I don't see any good _generic_ way to make
them RPC friendly, however, the error_t modules itself should come
with some common vtables:
extern struct error_params_vtable errror_int32_vtable;
extern struct error_params_vtable errror_uint32_vtable;
extern struct error_params_vtable errror_int64_vtable;
extern struct error_params_vtable errror_uint64_vtable;
extern struct error_params_vtable errror_float_vtable;
extern struct error_params_vtable errror_float_vtable;
extern struct error_params_vtable errror_double_vtable;
extern struct error_params_vtable errror_double_vtable;
extern struct error_params_vtable errror_string_vtable;
extern struct error_params_vtable errror_string_array_vtable;
With predictable convenience functions like:
int error_type_is_string_type (err);
void error_set_string (err, "foo");
char * error_get_string (err);
and so forth.
Prbly also worth making a hackerlab authority domain for errno errors
that are (symbolically) reasonably portable.
-t
- Re: [Gnu-arch-users] Nit, (continued)
- Re: [Gnu-arch-users] Nit, Robin Farine, 2003/10/22
- 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 <=
- Re: [Gnu-arch-users] Nit, Andrew Suffield, 2003/10/21
- Re: [Gnu-arch-users] Nit, Dustin Sallings, 2003/10/21
- Re: [Gnu-arch-users] Nit, Andrew Suffield, 2003/10/21
- Re: [Gnu-arch-users] Nit, Tom Lord, 2003/10/21
- Re: [Gnu-arch-users] Nit, Robert Collins, 2003/10/22
- Re: [Gnu-arch-users] Nit, Dustin Sallings, 2003/10/21
- Re: [Gnu-arch-users] Nit, Andrew Suffield, 2003/10/21
- Re: [Gnu-arch-users] Nit, Dustin Sallings, 2003/10/22
- Re: [Gnu-arch-users] Nit, Andrew Suffield, 2003/10/22
- Re: [Gnu-arch-users] Nit, Dustin Sallings, 2003/10/22