Line data Source code
1 : /*
2 : * Copyright (c) 2015 Cisco and/or its affiliates.
3 : * Licensed under the Apache License, Version 2.0 (the "License");
4 : * you may not use this file except in compliance with the License.
5 : * You may obtain a copy of the License at:
6 : *
7 : * http://www.apache.org/licenses/LICENSE-2.0
8 : *
9 : * Unless required by applicable law or agreed to in writing, software
10 : * distributed under the License is distributed on an "AS IS" BASIS,
11 : * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 : * See the License for the specific language governing permissions and
13 : * limitations under the License.
14 : */
15 : /*
16 : Copyright (c) 2001, 2002, 2003 Eliot Dresselhaus
17 :
18 : Permission is hereby granted, free of charge, to any person obtaining
19 : a copy of this software and associated documentation files (the
20 : "Software"), to deal in the Software without restriction, including
21 : without limitation the rights to use, copy, modify, merge, publish,
22 : distribute, sublicense, and/or sell copies of the Software, and to
23 : permit persons to whom the Software is furnished to do so, subject to
24 : the following conditions:
25 :
26 : The above copyright notice and this permission notice shall be
27 : included in all copies or substantial portions of the Software.
28 :
29 : THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
30 : EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
31 : MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
32 : NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
33 : LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
34 : OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
35 : WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
36 : */
37 :
38 : /* Error reporting. */
39 : #include <stdarg.h>
40 :
41 : #include <vppinfra/clib.h> /* for HAVE_ERRNO */
42 :
43 : #ifdef CLIB_LINUX_KERNEL
44 : #include <linux/unistd.h> /* for write */
45 : #include <linux/kernel.h> /* for printk */
46 : #endif
47 :
48 : #ifdef CLIB_UNIX
49 : #include <unistd.h> /* for write */
50 : #include <stdio.h> /* for printf */
51 : #define HAVE_ERRNO
52 : #endif
53 :
54 : #ifdef CLIB_STANDALONE
55 : #include <vppinfra/standalone_stdio.h> /* for printf */
56 : #endif
57 :
58 : #include <vppinfra/string.h>
59 : #include <vppinfra/mem.h>
60 : #include <vppinfra/vec.h>
61 : #include <vppinfra/format.h>
62 : #include <vppinfra/error.h>
63 : #include <vppinfra/hash.h>
64 : #include <vppinfra/os.h> /* for os_panic/os_exit/os_puts */
65 :
66 : typedef struct
67 : {
68 : clib_error_handler_func_t *func;
69 : void *arg;
70 : } clib_error_handler_t;
71 :
72 : static clib_error_handler_t *handlers = 0;
73 :
74 : __clib_export void
75 575 : clib_error_register_handler (clib_error_handler_func_t func, void *arg)
76 : {
77 575 : clib_error_handler_t h = {.func = func,.arg = arg, };
78 575 : vec_add1 (handlers, h);
79 575 : }
80 :
81 : static void
82 0 : debugger (void)
83 : {
84 0 : os_panic ();
85 0 : }
86 :
87 : static void
88 0 : error_exit (int code)
89 : {
90 0 : os_exit (code);
91 0 : }
92 :
93 : static u8 *
94 2021 : dispatch_message (u8 * msg)
95 : {
96 : word i;
97 :
98 2021 : if (!msg)
99 575 : return msg;
100 :
101 2346 : for (i = 0; i < vec_len (handlers); i++)
102 900 : handlers[i].func (handlers[i].arg, msg, vec_len (msg));
103 :
104 : /* If no message handler is specified provide a default one. */
105 1446 : if (vec_len (handlers) == 0)
106 546 : os_puts (msg, vec_len (msg), /* is_error */ 1);
107 :
108 1446 : return msg;
109 : }
110 :
111 : __clib_export void
112 1443 : _clib_error (int how_to_die, const char *function_name, uword line_number,
113 : const char *fmt, ...)
114 : {
115 1443 : u8 *msg = 0;
116 : va_list va;
117 :
118 1443 : if (function_name)
119 : {
120 1443 : msg = format (msg, "%s:", function_name);
121 1443 : if (line_number > 0)
122 1371 : msg = format (msg, "%wd:", line_number);
123 1443 : msg = format (msg, " ");
124 : }
125 :
126 1443 : va_start (va, fmt);
127 1443 : msg = va_format (msg, fmt, &va);
128 1443 : va_end (va);
129 :
130 : #ifdef HAVE_ERRNO
131 1443 : if (how_to_die & CLIB_ERROR_ERRNO_VALID)
132 0 : msg = format (msg, ": %s (errno %d)", strerror (errno), errno);
133 : #endif
134 :
135 1443 : if (vec_end (msg)[-1] != '\n')
136 1430 : vec_add1 (msg, '\n');
137 :
138 1443 : msg = dispatch_message (msg);
139 :
140 1443 : vec_free (msg);
141 :
142 1443 : if (how_to_die & CLIB_ERROR_ABORT)
143 0 : debugger ();
144 1443 : if (how_to_die & CLIB_ERROR_FATAL)
145 0 : error_exit (1);
146 1443 : }
147 :
148 : __clib_export clib_error_t *
149 249059 : _clib_error_return (clib_error_t *errors, any code, uword flags,
150 : const char *where, const char *fmt, ...)
151 : {
152 : clib_error_t *e;
153 : va_list va;
154 :
155 : #ifdef HAVE_ERRNO
156 : /* Save errno since it may be re-set before we'll need it. */
157 249059 : word errno_save = errno;
158 : #endif
159 :
160 249059 : va_start (va, fmt);
161 249059 : vec_add2 (errors, e, 1);
162 249059 : if (fmt)
163 249059 : e->what = va_format (0, fmt, &va);
164 :
165 : #ifdef HAVE_ERRNO
166 249059 : if (flags & CLIB_ERROR_ERRNO_VALID)
167 : {
168 173096 : if (e->what)
169 173096 : e->what = format (e->what, ": ");
170 173096 : e->what = format (e->what, "%s", strerror (errno_save));
171 : }
172 : #endif
173 :
174 249059 : e->where = (u8 *) where;
175 249059 : e->code = code;
176 249059 : e->flags = flags;
177 249059 : va_end (va);
178 249059 : return errors;
179 : }
180 :
181 : __clib_export void *
182 1362560 : clib_error_free_vector (clib_error_t * errors)
183 : {
184 : clib_error_t *e;
185 1609100 : vec_foreach (e, errors) vec_free (e->what);
186 1362560 : vec_free (errors);
187 1362560 : return 0;
188 : }
189 :
190 : __clib_export u8 *
191 7590 : format_clib_error (u8 * s, va_list * va)
192 : {
193 7590 : clib_error_t *errors = va_arg (*va, clib_error_t *);
194 : clib_error_t *e;
195 :
196 13454 : vec_foreach (e, errors)
197 : {
198 5864 : if (!e->what)
199 1725 : continue;
200 :
201 4139 : if (e->where)
202 : {
203 4139 : u8 *where = 0;
204 :
205 4139 : if (e > errors)
206 0 : where = format (where, "from ");
207 4139 : where = format (where, "%s", e->where);
208 :
209 4139 : s = format (s, "%v: ", where);
210 4139 : vec_free (where);
211 : }
212 :
213 4139 : s = format (s, "%v", e->what);
214 4139 : if ((vec_end (errors) - 1) != e)
215 0 : s = format (s, "\n");
216 : }
217 :
218 7590 : return s;
219 : }
220 :
221 : __clib_export clib_error_t *
222 578 : _clib_error_report (clib_error_t * errors)
223 : {
224 578 : if (errors)
225 : {
226 578 : u8 *msg = format (0, "%U", format_clib_error, errors);
227 :
228 578 : msg = dispatch_message (msg);
229 578 : vec_free (msg);
230 :
231 578 : if (errors->flags & CLIB_ERROR_ABORT)
232 0 : debugger ();
233 578 : if (errors->flags & CLIB_ERROR_FATAL)
234 0 : error_exit (1);
235 :
236 578 : clib_error_free (errors);
237 : }
238 578 : return 0;
239 : }
240 :
241 : #ifdef TEST
242 :
243 : static error_t *
244 : foo1 (int x)
245 : {
246 : return error_return (0, "x is odd %d", x);
247 : }
248 :
249 : static error_t *
250 : foo2 (int x)
251 : {
252 : return error_return (0, "x is even %d", x);
253 : }
254 :
255 : static error_t *
256 : foo (int x)
257 : {
258 : error_t *e;
259 : if (x & 1)
260 : e = foo1 (x);
261 : else
262 : e = foo2 (x);
263 : if (e)
264 : return error_return (e, 0);
265 : }
266 :
267 : static void
268 : error_handler (void *arg, char *msg, int msg_len)
269 : {
270 : write (2, msg, msg_len);
271 : }
272 :
273 : int
274 : main (int argc, char *argv[])
275 : {
276 : error_t *e;
277 :
278 : register_error_handler (error_handler, 0);
279 :
280 : e = foo (getpid ());
281 : if (e)
282 : error_report (e);
283 : return 0;
284 : }
285 :
286 : #endif
287 :
288 : /*
289 : * fd.io coding-style-patch-verification: ON
290 : *
291 : * Local Variables:
292 : * eval: (c-set-style "gnu")
293 : * End:
294 : */
|