LCOV - code coverage report
Current view: top level - vppinfra - error.c (source / functions) Hit Total Coverage
Test: coverage-filtered.info Lines: 72 85 84.7 %
Date: 2023-10-26 01:39:38 Functions: 7 9 77.8 %

          Line data    Source code
       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             : {
      68             :   clib_error_handler_func_t *func;
      69             :   void *arg;
      70             : } clib_error_handler_t;
      71             : 
      72             : static clib_error_handler_t *handlers = 0;
      73             : 
      74             : __clib_export void
      75         575 : clib_error_register_handler (clib_error_handler_func_t func, void *arg)
      76             : {
      77         575 :   clib_error_handler_t h = {.func = func,.arg = arg, };
      78         575 :   vec_add1 (handlers, h);
      79         575 : }
      80             : 
      81             : static void
      82           0 : debugger (void)
      83             : {
      84           0 :   os_panic ();
      85           0 : }
      86             : 
      87             : static void
      88           0 : error_exit (int code)
      89             : {
      90           0 :   os_exit (code);
      91           0 : }
      92             : 
      93             : static u8 *
      94        2021 : dispatch_message (u8 * msg)
      95             : {
      96             :   word i;
      97             : 
      98        2021 :   if (!msg)
      99         575 :     return msg;
     100             : 
     101        2346 :   for (i = 0; i < vec_len (handlers); i++)
     102         900 :     handlers[i].func (handlers[i].arg, msg, vec_len (msg));
     103             : 
     104             :   /* If no message handler is specified provide a default one. */
     105        1446 :   if (vec_len (handlers) == 0)
     106         546 :     os_puts (msg, vec_len (msg), /* is_error */ 1);
     107             : 
     108        1446 :   return msg;
     109             : }
     110             : 
     111             : __clib_export void
     112        1443 : _clib_error (int how_to_die, const char *function_name, uword line_number,
     113             :              const char *fmt, ...)
     114             : {
     115        1443 :   u8 *msg = 0;
     116             :   va_list va;
     117             : 
     118        1443 :   if (function_name)
     119             :     {
     120        1443 :       msg = format (msg, "%s:", function_name);
     121        1443 :       if (line_number > 0)
     122        1371 :         msg = format (msg, "%wd:", line_number);
     123        1443 :       msg = format (msg, " ");
     124             :     }
     125             : 
     126        1443 :   va_start (va, fmt);
     127        1443 :   msg = va_format (msg, fmt, &va);
     128        1443 :   va_end (va);
     129             : 
     130             : #ifdef HAVE_ERRNO
     131        1443 :   if (how_to_die & CLIB_ERROR_ERRNO_VALID)
     132           0 :     msg = format (msg, ": %s (errno %d)", strerror (errno), errno);
     133             : #endif
     134             : 
     135        1443 :   if (vec_end (msg)[-1] != '\n')
     136        1430 :     vec_add1 (msg, '\n');
     137             : 
     138        1443 :   msg = dispatch_message (msg);
     139             : 
     140        1443 :   vec_free (msg);
     141             : 
     142        1443 :   if (how_to_die & CLIB_ERROR_ABORT)
     143           0 :     debugger ();
     144        1443 :   if (how_to_die & CLIB_ERROR_FATAL)
     145           0 :     error_exit (1);
     146        1443 : }
     147             : 
     148             : __clib_export clib_error_t *
     149      249059 : _clib_error_return (clib_error_t *errors, any code, uword flags,
     150             :                     const char *where, const 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      249059 :   word errno_save = errno;
     158             : #endif
     159             : 
     160      249059 :   va_start (va, fmt);
     161      249059 :   vec_add2 (errors, e, 1);
     162      249059 :   if (fmt)
     163      249059 :     e->what = va_format (0, fmt, &va);
     164             : 
     165             : #ifdef HAVE_ERRNO
     166      249059 :   if (flags & CLIB_ERROR_ERRNO_VALID)
     167             :     {
     168      173096 :       if (e->what)
     169      173096 :         e->what = format (e->what, ": ");
     170      173096 :       e->what = format (e->what, "%s", strerror (errno_save));
     171             :     }
     172             : #endif
     173             : 
     174      249059 :   e->where = (u8 *) where;
     175      249059 :   e->code = code;
     176      249059 :   e->flags = flags;
     177      249059 :   va_end (va);
     178      249059 :   return errors;
     179             : }
     180             : 
     181             : __clib_export void *
     182     1362560 : clib_error_free_vector (clib_error_t * errors)
     183             : {
     184             :   clib_error_t *e;
     185     1609100 :   vec_foreach (e, errors) vec_free (e->what);
     186     1362560 :   vec_free (errors);
     187     1362560 :   return 0;
     188             : }
     189             : 
     190             : __clib_export u8 *
     191        7590 : format_clib_error (u8 * s, va_list * va)
     192             : {
     193        7590 :   clib_error_t *errors = va_arg (*va, clib_error_t *);
     194             :   clib_error_t *e;
     195             : 
     196       13454 :   vec_foreach (e, errors)
     197             :   {
     198        5864 :     if (!e->what)
     199        1725 :       continue;
     200             : 
     201        4139 :     if (e->where)
     202             :       {
     203        4139 :         u8 *where = 0;
     204             : 
     205        4139 :         if (e > errors)
     206           0 :           where = format (where, "from ");
     207        4139 :         where = format (where, "%s", e->where);
     208             : 
     209        4139 :         s = format (s, "%v: ", where);
     210        4139 :         vec_free (where);
     211             :       }
     212             : 
     213        4139 :     s = format (s, "%v", e->what);
     214        4139 :     if ((vec_end (errors) - 1) != e)
     215           0 :       s = format (s, "\n");
     216             :   }
     217             : 
     218        7590 :   return s;
     219             : }
     220             : 
     221             : __clib_export clib_error_t *
     222         578 : _clib_error_report (clib_error_t * errors)
     223             : {
     224         578 :   if (errors)
     225             :     {
     226         578 :       u8 *msg = format (0, "%U", format_clib_error, errors);
     227             : 
     228         578 :       msg = dispatch_message (msg);
     229         578 :       vec_free (msg);
     230             : 
     231         578 :       if (errors->flags & CLIB_ERROR_ABORT)
     232           0 :         debugger ();
     233         578 :       if (errors->flags & CLIB_ERROR_FATAL)
     234           0 :         error_exit (1);
     235             : 
     236         578 :       clib_error_free (errors);
     237             :     }
     238         578 :   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             :  */

Generated by: LCOV version 1.14