]>
git.proxmox.com Git - mirror_frr.git/blob - lib/ferr.c
2 * Copyright (c) 2015-16 David Lamparter, for NetDEF, Inc.
4 * Permission to use, copy, modify, and distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
28 DEFINE_MTYPE_STATIC(LIB
, ERRINFO
, "error information")
30 static pthread_key_t errkey
;
32 static void ferr_free(void *arg
)
34 XFREE(MTYPE_ERRINFO
, arg
);
37 static void err_key_init(void) __attribute__((_CONSTRUCTOR(500)));
38 static void err_key_init(void)
40 pthread_key_create(&errkey
, ferr_free
);
43 static void err_key_fini(void) __attribute__((_DESTRUCTOR(500)));
44 static void err_key_fini(void)
46 pthread_key_delete(errkey
);
49 const struct ferr
*ferr_get_last(ferr_r errval
)
51 struct ferr
*last_error
= pthread_getspecific(errkey
);
52 if (!last_error
|| last_error
->kind
== 0)
57 ferr_r
ferr_clear(void)
59 struct ferr
*last_error
= pthread_getspecific(errkey
);
65 static ferr_r
ferr_set_va(const char *file
, int line
, const char *func
,
66 enum ferr_kind kind
, const char *pathname
,
67 int errno_val
, const char *text
, va_list va
)
69 struct ferr
*error
= pthread_getspecific(errkey
);
72 error
= XCALLOC(MTYPE_ERRINFO
, sizeof(*error
));
75 zlog_err("out of memory while allocating error info");
77 abort(); /* raise() can return, but raise(SIGSEGV) shall
81 pthread_setspecific(errkey
, error
);
89 error
->unique_id
= jhash(text
, strlen(text
),
90 jhash(file
, strlen(file
), 0xd4ed0298));
92 error
->errno_val
= errno_val
;
94 snprintf(error
->pathname
, sizeof(error
->pathname
), "%s",
97 error
->pathname
[0] = '\0';
99 vsnprintf(error
->message
, sizeof(error
->message
), text
, va
);
103 ferr_r
ferr_set_internal(const char *file
, int line
, const char *func
,
104 enum ferr_kind kind
, const char *text
, ...)
109 rv
= ferr_set_va(file
, line
, func
, kind
, NULL
, 0, text
, va
);
114 ferr_r
ferr_set_internal_ext(const char *file
, int line
, const char *func
,
115 enum ferr_kind kind
, const char *pathname
,
116 int errno_val
, const char *text
, ...)
121 rv
= ferr_set_va(file
, line
, func
, kind
, pathname
, errno_val
, text
, va
);
126 #define REPLACE "$ERR"
127 void vty_print_error(struct vty
*vty
, ferr_r err
, const char *msg
, ...)
129 char tmpmsg
[512], *replacepos
;
130 const struct ferr
*last_error
= ferr_get_last(err
);
134 vsnprintf(tmpmsg
, sizeof(tmpmsg
), msg
, va
);
137 replacepos
= strstr(tmpmsg
, REPLACE
);
139 vty_out(vty
, "%s\n", tmpmsg
);
141 replacepos
[0] = '\0';
142 replacepos
+= sizeof(REPLACE
) - 1;
143 vty_out(vty
, "%s%s%s\n", tmpmsg
,
144 last_error
? last_error
->message
: "(no error?)",