aboutsummaryrefslogtreecommitdiffstats
path: root/doc/error.doc
blob: a91654999ab848604adcc0fb78a21463fa9ac99a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
The error routines.

The 'error' system I've implemented is intended to server 2 purpose, to
record the reason why a command failed and to record where in the libraries
the failure occurred.  It is more or less setup to record a 'trace' of which
library components were being traversed when the error occurred.

When an error is recorded, it is done so a as single unsigned long which is
composed of three parts.  The top byte is the 'library' number, the middle
12 bytes is the function code, and the bottom 12 bits is the 'reason' code.

Each 'library', or should a say, 'section' of the SSLeay library has a
different unique 'library' error number.  Each function in the library has
a number that is unique for that library.  Each 'library' also has a number
for each 'error reason' that is only unique for that 'library'.

Due to the way these error routines record a 'error trace', there is an
array per thread that is used to store the error codes.
The various functions in this library are used to access
and manipulate this array.

void ERR_put_error(int lib, int func,int reason);
	This routine records an error in library 'lib', function 'func'
and reason 'reason'.  As errors get 'put' into the buffer, they wrap
around and overwrite old errors if too many are written.  It is assumed
that the last errors are the most important.

unsigned long ERR_get_error(void );
	This function returns the last error added to the error buffer.
In effect it is popping the value off the buffer so repeated calls will
continue to return values until there are no more errors to return in which
case 0 is returned.

unsigned long ERR_peek_error(void );
	This function returns the value of the last error added to the
error buffer but does not 'pop' it from the buffer.

void ERR_clear_error(void );
	This function clears the error buffer, discarding all unread
errors.

While the above described error system obviously produces lots of different
error number, a method for 'reporting' these errors in a human readable
form is required.  To achieve this, each library has the option of
'registering' error strings.

typedef struct ERR_string_data_st
	{
	unsigned long error;
	char *string;
	} ERR_STRING_DATA;

The 'ERR_STRING_DATA' contains an error code and the corresponding text
string.  To add new function error strings for a library, the
ERR_STRING_DATA needs to be 'registered' with the library.

void ERR_load_strings(unsigned long lib,ERR_STRING_DATA *err);
	This function 'registers' the array of ERR_STRING_DATA pointed to by
'err' as error text strings for the error library 'lib'.

void ERR_free_strings(void);
	This function free()s all the loaded error strings.

char *ERR_error_string(unsigned long error,char *buf);
	This function returns a text string that is a human readable
version of the error represented by 'error'.  Buff should be at least 120
bytes long and if it is NULL, the return value is a pointer to a static
variable that will contain the error string, otherwise 'buf' is returned.
If there is not a text string registered for a particular error, a text
string containing the error number is returned instead.

void ERR_print_errors(BIO *bp);
void ERR_print_errors_fp(FILE *fp);
	This function is a convenience routine that prints the error string
for each error until all errors have been accounted for.

char *ERR_lib_error_string(unsigned long e);
char *ERR_func_error_string(unsigned long e);
char *ERR_reason_error_string(unsigned long e);
The above three functions return the 3 different components strings for the
error 'e'.  ERR_error_string() uses these functions.

void ERR_load_ERR_strings(void );
	This function 'registers' the error strings for the 'ERR' module.

void ERR_load_crypto_strings(void );
	This function 'register' the error strings for just about every
library in the SSLeay package except for the SSL routines.  There is no
need to ever register any error text strings and you will probably save in
program size.  If on the other hand you do 'register' all errors, it is
quite easy to determine why a particular routine failed.

As a final footnote as to why the error system is designed as it is.
1) I did not want a single 'global' error code.
2) I wanted to know which subroutine a failure occurred in.
3) For Windows NT etc, it should be simple to replace the 'key' routines
   with code to pass error codes back to the application.
4) I wanted the option of meaningful error text strings.

Late breaking news - the changes to support threads.

Each 'thread' has an 'ERR_STATE' state associated with it.
ERR_STATE *ERR_get_state(void ) will return the 'state' for the calling
thread/process.

ERR_remove_state(unsigned long pid); will 'free()' this state.  If pid == 0
the current 'thread/process' will have it's error state removed.
If you do not remove the error state of a thread, this could be considered a
form of memory leak, so just after 'reaping' a thread that has died,
call ERR_remove_state(pid).

Have a read of thread.doc for more details for what is required for
multi-threading support.  All the other error routines will
work correctly when using threads.