FD.io VPP  v19.01.1-17-ge106252
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
67 {
69  void *arg;
71 
72 static clib_error_handler_t *handlers = 0;
73 
74 void
76 {
77  clib_error_handler_t h = {.func = func,.arg = arg, };
78  vec_add1 (handlers, h);
79 }
80 
81 static void
82 debugger (void)
83 {
84  os_panic ();
85 }
86 
87 static void
88 error_exit (int code)
89 {
90  os_exit (code);
91 }
92 
93 static u8 *
95 {
96  word i;
97 
98  if (!msg)
99  return msg;
100 
101  for (i = 0; i < vec_len (handlers); i++)
102  handlers[i].func (handlers[i].arg, msg, vec_len (msg));
103 
104  /* If no message handler is specified provide a default one. */
105  if (vec_len (handlers) == 0)
106  os_puts (msg, vec_len (msg), /* is_error */ 1);
107 
108  return msg;
109 }
110 
111 void
112 _clib_error (int how_to_die,
113  char *function_name, uword line_number, char *fmt, ...)
114 {
115  u8 *msg = 0;
116  va_list va;
117 
118  if (function_name)
119  {
120  msg = format (msg, "%s:", function_name);
121  if (line_number > 0)
122  msg = format (msg, "%wd:", line_number);
123  msg = format (msg, " ");
124  }
125 
126  va_start (va, fmt);
127  msg = va_format (msg, fmt, &va);
128  va_end (va);
129 
130 #ifdef HAVE_ERRNO
131  if (how_to_die & CLIB_ERROR_ERRNO_VALID)
132  msg = format (msg, ": %s (errno %d)", strerror (errno), errno);
133 #endif
134 
135  if (vec_end (msg)[-1] != '\n')
136  vec_add1 (msg, '\n');
137 
138  msg = dispatch_message (msg);
139 
140  vec_free (msg);
141 
142  if (how_to_die & CLIB_ERROR_ABORT)
143  debugger ();
144  if (how_to_die & CLIB_ERROR_FATAL)
145  error_exit (1);
146 }
147 
148 clib_error_t *
149 _clib_error_return (clib_error_t * errors,
150  any code, uword flags, char *where, 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  word errno_save = errno;
158 #endif
159 
160  va_start (va, fmt);
161  vec_add2 (errors, e, 1);
162  if (fmt)
163  e->what = va_format (0, fmt, &va);
164 
165 #ifdef HAVE_ERRNO
167  {
168  if (e->what)
169  e->what = format (e->what, ": ");
170  e->what = format (e->what, "%s", strerror (errno_save));
171  }
172 #endif
173 
174  e->where = (u8 *) where;
175  e->code = code;
176  e->flags = flags;
177  va_end (va);
178  return errors;
179 }
180 
181 void *
183 {
184  clib_error_t *e;
185  vec_foreach (e, errors) vec_free (e->what);
186  vec_free (errors);
187  return 0;
188 }
189 
190 u8 *
191 format_clib_error (u8 * s, va_list * va)
192 {
193  clib_error_t *errors = va_arg (*va, clib_error_t *);
194  clib_error_t *e;
195 
196  vec_foreach (e, errors)
197  {
198  if (!e->what)
199  continue;
200 
201  if (e->where)
202  {
203  u8 *where = 0;
204 
205  if (e > errors)
206  where = format (where, "from ");
207  where = format (where, "%s", e->where);
208 
209  s = format (s, "%v: ", where);
210  vec_free (where);
211  }
212 
213  s = format (s, "%v\n", e->what);
214  }
215 
216  return s;
217 }
218 
219 clib_error_t *
220 _clib_error_report (clib_error_t * errors)
221 {
222  if (errors)
223  {
224  u8 *msg = format (0, "%U", format_clib_error, errors);
225 
226  msg = dispatch_message (msg);
227  vec_free (msg);
228 
229  if (errors->flags & CLIB_ERROR_ABORT)
230  debugger ();
231  if (errors->flags & CLIB_ERROR_FATAL)
232  error_exit (1);
233 
234  clib_error_free (errors);
235  }
236  return 0;
237 }
238 
239 #ifdef TEST
240 
241 static error_t *
242 foo1 (int x)
243 {
244  return error_return (0, "x is odd %d", x);
245 }
246 
247 static error_t *
248 foo2 (int x)
249 {
250  return error_return (0, "x is even %d", x);
251 }
252 
253 static error_t *
254 foo (int x)
255 {
256  error_t *e;
257  if (x & 1)
258  e = foo1 (x);
259  else
260  e = foo2 (x);
261  if (e)
262  return error_return (e, 0);
263 }
264 
265 static void
266 error_handler (void *arg, char *msg, int msg_len)
267 {
268  write (2, msg, msg_len);
269 }
270 
271 int
272 main (int argc, char *argv[])
273 {
274  error_t *e;
275 
276  register_error_handler (error_handler, 0);
277 
278  e = foo (getpid ());
279  if (e)
280  error_report (e);
281  return 0;
282 }
283 
284 #endif
285 
286 /*
287  * fd.io coding-style-patch-verification: ON
288  *
289  * Local Variables:
290  * eval: (c-set-style "gnu")
291  * End:
292  */
u8 * format_clib_error(u8 *s, va_list *va)
Definition: error.c:191
u32 flags
Definition: vhost_user.h:115
void os_puts(u8 *string, uword length, uword is_error)
Definition: unix-misc.c:191
Optimized string handling code, including c11-compliant "safe C library" variants.
void os_panic(void)
Definition: unix-misc.c:174
#define vec_add1(V, E)
Add 1 element to end of vector (unspecified alignment).
Definition: vec.h:525
word any
Definition: types.h:139
#define vec_add2(V, P, N)
Add N elements to end of vector V, return pointer to new elements in P.
Definition: vec.h:564
int i
u8 * format(u8 *s, const char *fmt,...)
Definition: format.c:419
u8 * va_format(u8 *s, const char *fmt, va_list *va)
Definition: format.c:387
void clib_error_register_handler(clib_error_handler_func_t func, void *arg)
Definition: error.c:75
static u8 * dispatch_message(u8 *msg)
Definition: error.c:94
unsigned char u8
Definition: types.h:56
uword flags
Definition: clib_error.h:29
i64 word
Definition: types.h:111
#define vec_end(v)
End (last data address) of vector.
void * clib_error_free_vector(clib_error_t *errors)
Definition: error.c:182
#define vec_free(V)
Free vector&#39;s memory (no header).
Definition: vec.h:341
void os_exit(int code)
Definition: unix-misc.c:182
clib_error_handler_func_t * func
Definition: error.c:68
void clib_error_handler_func_t(void *arg, u8 *msg, int msg_len)
Definition: error.h:56
static void error_exit(int code)
Definition: error.c:88
int main(int argc, char **argv)
Definition: persist.c:215
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
u64 uword
Definition: types.h:112
#define clib_error_free(e)
Definition: error.h:86
#define vec_foreach(var, vec)
Vector iterator.
const u8 * where
Definition: clib_error.h:27
static void debugger(void)
Definition: error.c:82
CLIB vectors are ubiquitous dynamically resized arrays with by user defined "headers".