FD.io VPP  v21.01.1
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 __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  */
__clib_export u8 * va_format(u8 *s, const char *fmt, va_list *va)
Definition: format.c:387
vl_api_wireguard_peer_flags_t flags
Definition: wireguard.api:105
void os_puts(u8 *string, uword length, uword is_error)
Definition: unix-misc.c:192
Optimized string handling code, including c11-compliant "safe C library" variants.
void os_panic(void)
Definition: unix-misc.c:175
__clib_export void * clib_error_free_vector(clib_error_t *errors)
Definition: error.c:182
#define vec_add1(V, E)
Add 1 element to end of vector (unspecified alignment).
Definition: vec.h:592
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:630
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
description fragment has unexpected format
Definition: map.api:433
__clib_export void clib_error_register_handler(clib_error_handler_func_t func, void *arg)
Definition: error.c:75
#define vec_end(v)
End (last data address) of vector.
vec_header_t h
Definition: buffer.c:322
int cJSON_bool fmt
Definition: cJSON.h:160
sll srl srl sll sra u16x4 i
Definition: vector_sse42.h:317
#define vec_free(V)
Free vector&#39;s memory (no header).
Definition: vec.h:380
void os_exit(int code)
Definition: unix-misc.c:183
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
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
int main(int argc, char **argv)
Definition: health_check.c:24
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
__clib_export u8 * format_clib_error(u8 *s, va_list *va)
Definition: error.c:191
static void debugger(void)
Definition: error.c:82
CLIB vectors are ubiquitous dynamically resized arrays with by user defined "headers".