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:
7 * http://www.apache.org/licenses/LICENSE-2.0
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.
16 Copyright (c) 2001, 2002, 2003 Eliot Dresselhaus
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:
26 The above copyright notice and this permission notice shall be
27 included in all copies or substantial portions of the Software.
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.
38 /* Error reporting. */
41 #include <vppinfra/clib.h> /* for HAVE_ERRNO */
43 #ifdef CLIB_LINUX_KERNEL
44 #include <linux/unistd.h> /* for write */
45 #include <linux/kernel.h> /* for printk */
49 #include <unistd.h> /* for write */
50 #include <stdio.h> /* for printf */
54 #ifdef CLIB_STANDALONE
55 #include <vppinfra/standalone_stdio.h> /* for printf */
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 */
67 clib_error_handler_func_t * func;
69 } clib_error_handler_t;
71 static clib_error_handler_t * handlers = 0;
73 void clib_error_register_handler (clib_error_handler_func_t func, void * arg)
75 clib_error_handler_t h = { .func = func, .arg = arg, };
76 vec_add1 (handlers, h);
79 static void debugger (void)
84 static void error_exit (int code)
89 static u8 * dispatch_message (u8 * msg)
96 for (i = 0; i < vec_len (handlers); i++)
97 handlers[i].func (handlers[i].arg, msg, vec_len (msg));
99 /* If no message handler is specified provide a default one. */
100 if (vec_len (handlers) == 0)
101 os_puts (msg, vec_len (msg), /* is_error */ 1);
106 void _clib_error (int how_to_die,
107 char * function_name,
116 msg = format (msg, "%s:", function_name);
118 msg = format (msg, "%wd:", line_number);
119 msg = format (msg, " ");
123 msg = va_format (msg, fmt, &va);
127 if (how_to_die & CLIB_ERROR_ERRNO_VALID)
128 msg = format (msg, ": %s (errno %d)", strerror (errno), errno);
131 if (vec_end (msg)[-1] != '\n')
132 vec_add1 (msg, '\n');
134 msg = dispatch_message (msg);
138 if (how_to_die & CLIB_ERROR_ABORT)
140 if (how_to_die & CLIB_ERROR_FATAL)
144 clib_error_t * _clib_error_return (clib_error_t * errors,
154 /* Save errno since it may be re-set before we'll need it. */
155 word errno_save = errno;
159 vec_add2 (errors, e, 1);
161 e->what = va_format (0, fmt, &va);
164 if (flags & CLIB_ERROR_ERRNO_VALID)
167 e->what = format (e->what, ": ");
168 e->what = format (e->what, "%s", strerror (errno_save));
172 e->where = (u8 *) where;
179 void * clib_error_free_vector (clib_error_t * errors)
182 vec_foreach (e, errors)
188 u8 * format_clib_error (u8 * s, va_list * va)
190 clib_error_t * errors = va_arg (*va, clib_error_t *);
193 vec_foreach (e, errors)
203 where = format (where, "from ");
204 where = format (where, "%s", e->where);
206 s = format (s, "%v: ", where);
210 s = format (s, "%v\n", e->what);
216 clib_error_t * _clib_error_report (clib_error_t * errors)
220 u8 * msg = format (0, "%U", format_clib_error, errors);
222 msg = dispatch_message (msg);
225 if (errors->flags & CLIB_ERROR_ABORT)
227 if (errors->flags & CLIB_ERROR_FATAL)
230 clib_error_free (errors);
237 static error_t * foo1 (int x)
239 return error_return (0, "x is odd %d", x);
242 static error_t * foo2 (int x)
244 return error_return (0, "x is even %d", x);
247 static error_t * foo (int x)
255 return error_return (e, 0);
258 static void error_handler (void * arg, char * msg, int msg_len)
260 write (2, msg, msg_len);
263 int main (int argc, char * argv[])
267 register_error_handler (error_handler, 0);