-
Notifications
You must be signed in to change notification settings - Fork 2
/
Errors.h
121 lines (81 loc) · 4.58 KB
/
Errors.h
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
116
117
118
119
120
121
/*
Copyright (c) 2015 Colum Paget <[email protected]>
* SPDX-License-Identifier: GPL-3.0
*/
#ifndef LIBUSEFUL_ERRORS_H
#define LIBUSEFUL_ERRORS_H
#include <stdint.h>
#include "List.h"
#define ERRFLAG_ERRNO 1
#define ERRFLAG_DEBUG 2
#define ERRFLAG_CLEAR 4
#define ERRFLAG_NOTTY 8
#define ERRFLAG_SYSLOG 16
#define ERRFLAG_ABORT 32
/*
The libUseful error system builds a list of errors as the occur. This way, if multiple errors happen within
a function (e.g. multiple files fail to open) none of these errors are 'lost' when the next one happens. Errors
leave the queue when they are more than 2 seconds old, and can also be cleared by calling 'ErrorsClear'. They
can be accessed by calling 'ErrorsGet' which returns a list of TError objects. Normal use is that a function
returns a failure value, and the code then calls 'ErrorsGet' and steps through the errors, displaying them
to the user or whatever.
Errors are injected into the list with RaiseError like this:
RaiseError(ERRFLAG_ERRNO, "ServiceConnect", "host=%s port=%d",Host, Port);
the first argument, 'flags' can take a bitmask of of the above defined ERRFLAG_ values
the second argument 'where' is a user defined string specifying where this error occurred, or what was being
done when it occurred
the third argument is a printf-style format string, and arguments after that are handled printf-style
RaiseError grabs information about which sourcecode file, and which line in that file, it was called at.
It adds a 'TError' object to the errors list with all the information in. It prints an error message to stderr,
depending on some conditions mentioned below.
If the flag ERRFLAG_ERRNO is passed then the 'errval' member of TError will contain the errno value that was in
the system when RaiseError was called. Also, if RaiseError prints out an error, then the string description of
errno, as obtained from strerror will be appended to the output message.
By default RaiseError will not print out to stderr if stderr is not a tty, in order to prevent sending errors
up pipes and sockets to applications that aren't expecting them. If you want raise error to print even when
stderr is not a tty then either pass the ERRFLAG_NOTTY value, like this
RaiseError(ERRFLAG_ERRNO|ERRFLAG_NOTTY, "ServiceConnect", "host=%s port=%d",Host, Port);
or, if you don't want to have to do this every time you call RaiseError, then you can achieve the same by
setting the libUseful internal boolean value 'Error:notty', like this:
ListUsefulSetValue("Error:notty","Y")
If the ERRFLAG_SYSLOG flag is passed, like this:
RaiseError(ERRFLAG_ERRNO|ERRFLAG_SYSLOG, "ServiceConnect", "host=%s port=%d",Host, Port);
Then the error will be logged to the system logger. Alternatively if the LibUseful value 'Error:Syslog' is set, like this:
ListUsefulSetValue("Error:Syslog","Y")
then all error and debug messages are sent to the system logger via syslog.
If the flag ERRFLAG_DEBUG is set then RaiseError won't print anything out by default. So this line:
RaiseError(ERRFLAG_DEBUG, "ServiceConnect", "host=%s port=%d",Host, Port);
Wouldn't produce any output normally. This allows you to have debugging lines that can be switched on as
needed. There's two ways to activate debugging. Firstly there's the environment variable 'LIBUSEFUL_DEBUG'.
When this environment variable exists and is non-empty then RaiseError calls will print out, even if they're
passed ERRFLAG_DEBUG. Secondly there's the libuseful internal value 'Error:Debug'. When this has been set to
'true' (or 'y' or 'yes') with LibUsefulSetValue, then again all debugging lines will print out.
If ERRFLAG_DEBUG is passed then nothing is EVER added to the ErrorList, the 'error' is just a debugging line
and it's assumed that the program continues normally.
If the libUseful internal value 'Error:Silent' is set true/yes/y with ListUsefulSetValue then RaiseError never
prints errors to stderr, regardless of any other config.
*/
typedef struct
{
uint64_t when;
char *where;
char *file;
char *msg;
int line;
int errval;
} TError;
#ifdef __cplusplus
extern "C" {
#endif
//call 'RaiseError' to add an error into the error sytem
#define RaiseError(flags, where, fmt, ...) InternalRaiseError(flags, where, __FILE__, __LINE__, fmt, ##__VA_ARGS__)
//clears the list of errors
void ErrorsClear();
//returns a list of TError objects
ListNode *ErrorsGet();
//this function isn't supposed to be used by you! You never saw this!
void InternalRaiseError(int flags, const char *where, const char *file, int line, const char *FmtStr, ...);
#ifdef __cplusplus
}
#endif
#endif