FD.io VPP  v16.06
Vector Packet Processing
error.c
Go to the documentation of this file.
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 {
68  void * arg;
70 
71 static clib_error_handler_t * handlers = 0;
72 
74 {
75  clib_error_handler_t h = { .func = func, .arg = arg, };
76  vec_add1 (handlers, h);
77 }
78 
79 static void debugger (void)
80 {
81  os_panic ();
82 }
83 
84 static void error_exit (int code)
85 {
86  os_exit (code);
87 }
88 
89 static u8 * dispatch_message (u8 * msg)
90 {
91  word i;
92 
93  if (! msg)
94  return msg;
95 
96  for (i = 0; i < vec_len (handlers); i++)
97  handlers[i].func (handlers[i].arg, msg, vec_len (msg));
98 
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);
102 
103  return msg;
104 }
105 
106 void _clib_error (int how_to_die,
107  char * function_name,
108  uword line_number,
109  char * fmt, ...)
110 {
111  u8 * msg = 0;
112  va_list va;
113 
114  if (function_name)
115  {
116  msg = format (msg, "%s:", function_name);
117  if (line_number > 0)
118  msg = format (msg, "%wd:", line_number);
119  msg = format (msg, " ");
120  }
121 
122  va_start (va, fmt);
123  msg = va_format (msg, fmt, &va);
124  va_end (va);
125 
126 #ifdef HAVE_ERRNO
127  if (how_to_die & CLIB_ERROR_ERRNO_VALID)
128  msg = format (msg, ": %s (errno %d)", strerror (errno), errno);
129 #endif
130 
131  if (vec_end (msg)[-1] != '\n')
132  vec_add1 (msg, '\n');
133 
134  msg = dispatch_message (msg);
135 
136  vec_free (msg);
137 
138  if (how_to_die & CLIB_ERROR_ABORT)
139  debugger ();
140  if (how_to_die & CLIB_ERROR_FATAL)
141  error_exit (1);
142 }
143 
144 clib_error_t * _clib_error_return (clib_error_t * errors,
145  any code,
146  uword flags,
147  char * where,
148  char * fmt, ...)
149 {
150  clib_error_t * e;
151  va_list va;
152 
153 #ifdef HAVE_ERRNO
154  /* Save errno since it may be re-set before we'll need it. */
155  word errno_save = errno;
156 #endif
157 
158  va_start (va, fmt);
159  vec_add2 (errors, e, 1);
160  if (fmt)
161  e->what = va_format (0, fmt, &va);
162 
163 #ifdef HAVE_ERRNO
165  {
166  if (e->what)
167  e->what = format (e->what, ": ");
168  e->what = format (e->what, "%s", strerror (errno_save));
169  }
170 #endif
171 
172  e->where = (u8 *) where;
173  e->code = code;
174  e->flags = flags;
175  va_end (va);
176  return errors;
177 }
178 
180 {
181  clib_error_t * e;
182  vec_foreach (e, errors)
183  vec_free (e->what);
184  vec_free (errors);
185  return 0;
186 }
187 
188 u8 * format_clib_error (u8 * s, va_list * va)
189 {
190  clib_error_t * errors = va_arg (*va, clib_error_t *);
191  clib_error_t * e;
192 
193  vec_foreach (e, errors)
194  {
195  if (! e->what)
196  continue;
197 
198  if (e->where)
199  {
200  u8 * where = 0;
201 
202  if (e > errors)
203  where = format (where, "from ");
204  where = format (where, "%s", e->where);
205 
206  s = format (s, "%v: ", where);
207  vec_free (where);
208  }
209 
210  s = format (s, "%v\n", e->what);
211  }
212 
213  return s;
214 }
215 
216 clib_error_t * _clib_error_report (clib_error_t * errors)
217 {
218  if (errors)
219  {
220  u8 * msg = format (0, "%U", format_clib_error, errors);
221 
222  msg = dispatch_message (msg);
223  vec_free (msg);
224 
225  if (errors->flags & CLIB_ERROR_ABORT)
226  debugger ();
227  if (errors->flags & CLIB_ERROR_FATAL)
228  error_exit (1);
229 
230  clib_error_free (errors);
231  }
232  return 0;
233 }
234 
235 #ifdef TEST
236 
237 static error_t * foo1 (int x)
238 {
239  return error_return (0, "x is odd %d", x);
240 }
241 
242 static error_t * foo2 (int x)
243 {
244  return error_return (0, "x is even %d", x);
245 }
246 
247 static error_t * foo (int x)
248 {
249  error_t * e;
250  if (x & 1)
251  e = foo1 (x);
252  else
253  e = foo2 (x);
254  if (e)
255  return error_return (e, 0);
256 }
257 
258 static void error_handler (void * arg, char * msg, int msg_len)
259 {
260  write (2, msg, msg_len);
261 }
262 
263 int main (int argc, char * argv[])
264 {
265  error_t * e;
266 
267  register_error_handler (error_handler, 0);
268 
269  e = foo (getpid ());
270  if (e)
271  error_report (e);
272  return 0;
273 }
274 
275 #endif
sll srl srl sll sra u16x4 i
Definition: vector_sse2.h:267
void * clib_error_free_vector(clib_error_t *errors)
Definition: error.c:179
void os_puts(u8 *string, uword length, uword is_error)
Definition: unix-misc.c:175
u8 * format_clib_error(u8 *s, va_list *va)
Definition: error.c:188
void os_panic(void)
Definition: unix-misc.c:165
#define vec_add1(V, E)
Add 1 element to end of vector (unspecified alignment).
Definition: vec.h:480
#define vec_add2(V, P, N)
Add N elements to end of vector V, return pointer to new elements in P.
Definition: vec.h:519
u8 * what
Definition: error.h:77
uword flags
Definition: error.h:82
void clib_error_handler_func_t(void *arg, u8 *msg, int msg_len)
Definition: error.h:56
#define vec_end(v)
End (last data address) of vector.
any code
Definition: error.h:85
static void error_exit(int code)
Definition: error.c:84
word any
Definition: types.h:137
u8 * va_format(u8 *s, char *fmt, va_list *va)
Definition: format.c:374
#define vec_free(V)
Free vector&#39;s memory (no header).
Definition: vec.h:298
#define clib_error_free(e)
Definition: error.h:97
void os_exit(int code)
Definition: unix-misc.c:169
clib_error_handler_func_t * func
Definition: error.c:67
u8 * format(u8 *s, char *fmt,...)
Definition: format.c:405
void clib_error_register_handler(clib_error_handler_func_t func, void *arg)
Definition: error.c:73
u64 uword
Definition: types.h:112
static void debugger(void)
Definition: error.c:79
i64 word
Definition: types.h:111
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
unsigned char u8
Definition: types.h:56
#define vec_foreach(var, vec)
Vector iterator.
int main(int argc, char *argv[])
Definition: elftool.c:369
const u8 * where
Definition: error.h:80
u32 flags
Definition: vhost-user.h:73
static u8 * dispatch_message(u8 *msg)
Definition: error.c:89
CLIB vectors are ubiquitous dynamically resized arrays with by user defined "headers".