FD.io VPP  v21.10.1-2-g0a485f517
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 
73 
74 __clib_export 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 __clib_export 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_export 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 __clib_export 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 __clib_export 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", e->what);
214  if ((vec_end (errors) - 1) != e)
215  s = format (s, "\n");
216  }
217 
218  return s;
219 }
220 
221 __clib_export clib_error_t *
222 _clib_error_report (clib_error_t * errors)
223 {
224  if (errors)
225  {
226  u8 *msg = format (0, "%U", format_clib_error, errors);
227 
228  msg = dispatch_message (msg);
229  vec_free (msg);
230 
231  if (errors->flags & CLIB_ERROR_ABORT)
232  debugger ();
233  if (errors->flags & CLIB_ERROR_FATAL)
234  error_exit (1);
235 
236  clib_error_free (errors);
237  }
238  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  */
os.h
clib_error_handler_t::func
clib_error_handler_func_t * func
Definition: error.c:68
os_panic
void os_panic(void)
Definition: pnat_test_stubs.h:19
CLIB_ERROR_ABORT
@ CLIB_ERROR_ABORT
Definition: error_bootstrap.h:49
handlers
static clib_error_handler_t * handlers
Definition: error.c:72
clib.h
os_exit
void os_exit(int code)
Definition: pnat_test_stubs.h:20
string.h
vec_end
#define vec_end(v)
End (last data address) of vector.
Definition: vec_bootstrap.h:197
va_format
__clib_export u8 * va_format(u8 *s, const char *fmt, va_list *va)
Definition: format.c:391
h
h
Definition: flowhash_template.h:372
format_clib_error
__clib_export u8 * format_clib_error(u8 *s, va_list *va)
Definition: error.c:191
hash.h
vec_len
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
Definition: vec_bootstrap.h:142
error.h
vec_add2
#define vec_add2(V, P, N)
Add N elements to end of vector V, return pointer to new elements in P.
Definition: vec.h:644
vec_add1
#define vec_add1(V, E)
Add 1 element to end of vector (unspecified alignment).
Definition: vec.h:606
error_exit
static void error_exit(int code)
Definition: error.c:88
any
word any
Definition: types.h:139
clib_error_t::where
const u8 * where
Definition: clib_error.h:27
uword
u64 uword
Definition: types.h:112
clib_error_t::code
any code
Definition: clib_error.h:32
clib_error_register_handler
__clib_export void clib_error_register_handler(clib_error_handler_func_t func, void *arg)
Definition: error.c:75
format.h
debugger
static void debugger(void)
Definition: error.c:82
clib_error_handler_func_t
void clib_error_handler_func_t(void *arg, u8 *msg, int msg_len)
Definition: error.h:56
CLIB_ERROR_ERRNO_VALID
@ CLIB_ERROR_ERRNO_VALID
Definition: error_bootstrap.h:51
fmt
int cJSON_bool fmt
Definition: cJSON.h:160
vec_free
#define vec_free(V)
Free vector's memory (no header).
Definition: vec.h:395
main
int main(int argc, char **argv)
Definition: health_check.c:24
format
description fragment has unexpected format
Definition: map.api:433
vec_foreach
#define vec_foreach(var, vec)
Vector iterator.
Definition: vec_bootstrap.h:213
vec.h
u8
unsigned char u8
Definition: types.h:56
clib_error_t
Definition: clib_error.h:21
i
int i
Definition: flowhash_template.h:376
word
i64 word
Definition: types.h:111
clib_error_free
#define clib_error_free(e)
Definition: error.h:86
dispatch_message
static u8 * dispatch_message(u8 *msg)
Definition: error.c:94
mem.h
clib_error_t::flags
uword flags
Definition: clib_error.h:29
clib_error_handler_t
Definition: error.c:66
os_puts
void os_puts(u8 *string, uword length, uword is_error)
Definition: unix-misc.c:192
CLIB_ERROR_FATAL
@ CLIB_ERROR_FATAL
Definition: error_bootstrap.h:48
clib_error_t::what
u8 * what
Definition: clib_error.h:24
function_name
unsigned char function_name[]
Definition: ad.c:32
clib_error_free_vector
__clib_export void * clib_error_free_vector(clib_error_t *errors)
Definition: error.c:182
clib_error_handler_t::arg
void * arg
Definition: error.c:69
flags
vl_api_wireguard_peer_flags_t flags
Definition: wireguard.api:105