summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/assert/assert.h98
-rw-r--r--lib/clippy.c14
-rw-r--r--lib/compiler.h6
-rw-r--r--lib/libfrr_trace.c2
-rw-r--r--lib/link_state.c2
-rw-r--r--lib/log.c11
-rw-r--r--lib/log.h2
-rw-r--r--lib/routing_nb.c2
-rw-r--r--lib/routing_nb_config.c2
-rw-r--r--lib/subdir.am5
-rw-r--r--lib/thread.c2
-rw-r--r--lib/xref.h1
-rw-r--r--lib/zassert.h45
-rw-r--r--lib/zebra.h2
-rw-r--r--lib/zlog.c30
-rw-r--r--lib/zlog.h2
16 files changed, 150 insertions, 76 deletions
diff --git a/lib/assert/assert.h b/lib/assert/assert.h
new file mode 100644
index 0000000000..fbdbd52ce8
--- /dev/null
+++ b/lib/assert/assert.h
@@ -0,0 +1,98 @@
+/*
+ * Copyright (c) 2021 David Lamparter, for NetDEF, Inc.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* WARNING: this file is "special" in that it overrides the system-provided
+ * assert.h by being on the include path before it. That means it should
+ * provide the functional equivalent.
+ *
+ * This is intentional because FRR extends assert() to write to the log and
+ * add backtraces. Overriding the entire file is the simplest and most
+ * reliable way to get this to work; there were problems previously with the
+ * system assert.h getting included afterwards and redefining assert() back to
+ * the system variant.
+ */
+
+#ifndef _FRR_ASSERT_H
+#define _FRR_ASSERT_H
+
+#include "xref.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef __cplusplus
+/* C++ has this built-in, but C provides it in assert.h for >=C11. Since we
+ * replace assert.h entirely, we need to provide it here too.
+ */
+#define static_assert _Static_assert
+#endif
+
+struct xref_assert {
+ struct xref xref;
+
+ const char *expr;
+ const char *extra, *args;
+};
+
+extern void _zlog_assert_failed(const struct xref_assert *xref,
+ const char *extra, ...) PRINTFRR(2, 3)
+ __attribute__((noreturn));
+
+/* the "do { } while (expr_)" is there to get a warning for assignments inside
+ * the assert expression aka "assert(x = 1)". The (necessary) braces around
+ * expr_ in the if () statement would suppress these warnings. Since
+ * _zlog_assert_failed() is noreturn, the while condition will never be
+ * checked.
+ */
+#define assert(expr_) \
+ ({ \
+ static const struct xref_assert _xref __attribute__( \
+ (used)) = { \
+ .xref = XREF_INIT(XREFT_ASSERT, NULL, __func__), \
+ .expr = #expr_, \
+ }; \
+ XREF_LINK(_xref.xref); \
+ if (__builtin_expect((expr_) ? 0 : 1, 0)) \
+ do { \
+ _zlog_assert_failed(&_xref, NULL); \
+ } while (expr_); \
+ })
+
+#define assertf(expr_, extra_, ...) \
+ ({ \
+ static const struct xref_assert _xref __attribute__( \
+ (used)) = { \
+ .xref = XREF_INIT(XREFT_ASSERT, NULL, __func__), \
+ .expr = #expr_, \
+ .extra = extra_, \
+ .args = #__VA_ARGS__, \
+ }; \
+ XREF_LINK(_xref.xref); \
+ if (__builtin_expect((expr_) ? 0 : 1, 0)) \
+ do { \
+ _zlog_assert_failed(&_xref, extra_, \
+ ##__VA_ARGS__); \
+ } while (expr_); \
+ })
+
+#define zassert assert
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _FRR_ASSERT_H */
diff --git a/lib/clippy.c b/lib/clippy.c
index 6223697ae9..7ca99c9a94 100644
--- a/lib/clippy.c
+++ b/lib/clippy.c
@@ -106,12 +106,7 @@ int main(int argc, char **argv)
/* and now for the ugly part... provide simplified logging functions so we
* don't need to link libzebra (which would be a circular build dep) */
-#ifdef __ASSERT_FUNCTION
-#undef __ASSERT_FUNCTION
-#endif
-
#include "log.h"
-#include "zassert.h"
void vzlogx(const struct xref_logmsg *xref, int prio,
const char *format, va_list args)
@@ -120,15 +115,6 @@ void vzlogx(const struct xref_logmsg *xref, int prio,
fputs("\n", stderr);
}
-void _zlog_assert_failed(const char *assertion, const char *file,
- unsigned int line, const char *function)
-{
- fprintf(stderr,
- "Assertion `%s' failed in file %s, line %u, function %s",
- assertion, file, line, (function ? function : "?"));
- abort();
-}
-
void memory_oom(size_t size, const char *name)
{
abort();
diff --git a/lib/compiler.h b/lib/compiler.h
index b7a142bdee..86cf347e01 100644
--- a/lib/compiler.h
+++ b/lib/compiler.h
@@ -373,6 +373,10 @@ CPP_NOTICE("time to remove this CONFDATE block")
#else /* !_FRR_ATTRIBUTE_PRINTFRR */
#define PRINTFRR(a, b) __attribute__((format(printf, a, b)))
+/* frr-format plugin is C-only for now, so no point in doing these shenanigans
+ * for C++... (also they can break some C++ stuff...)
+ */
+#ifndef __cplusplus
/* these should be typedefs, but might also be #define */
#ifdef uint64_t
#undef uint64_t
@@ -400,6 +404,8 @@ _Static_assert(sizeof(_uint64_t) == 8 && sizeof(_int64_t) == 8,
#define PRIu64 "llu"
#define PRId64 "lld"
#define PRIx64 "llx"
+
+#endif /* !__cplusplus */
#endif /* !_FRR_ATTRIBUTE_PRINTFRR */
#ifdef __cplusplus
diff --git a/lib/libfrr_trace.c b/lib/libfrr_trace.c
index 2f300e6ee1..59320322ca 100644
--- a/lib/libfrr_trace.c
+++ b/lib/libfrr_trace.c
@@ -1,4 +1,6 @@
#define TRACEPOINT_CREATE_PROBES
#define TRACEPOINT_DEFINE
+#include <zebra.h>
+
#include "libfrr_trace.h"
diff --git a/lib/link_state.c b/lib/link_state.c
index 8606f8eb09..afeb89c592 100644
--- a/lib/link_state.c
+++ b/lib/link_state.c
@@ -22,6 +22,8 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
+#include <zebra.h>
+
#include "if.h"
#include "linklist.h"
#include "log.h"
diff --git a/lib/log.c b/lib/log.c
index ca2f501686..15fdfd4b0a 100644
--- a/lib/log.c
+++ b/lib/log.c
@@ -311,17 +311,6 @@ void zlog_thread_info(int log_level)
zlog(log_level, "Current thread not known/applicable");
}
-void _zlog_assert_failed(const char *assertion, const char *file,
- unsigned int line, const char *function)
-{
- zlog(LOG_CRIT, "Assertion `%s' failed in file %s, line %u, function %s",
- assertion, file, line, (function ? function : "?"));
- zlog_backtrace(LOG_CRIT);
- zlog_thread_info(LOG_CRIT);
- log_memstats(stderr, "log");
- abort();
-}
-
void memory_oom(size_t size, const char *name)
{
zlog(LOG_CRIT,
diff --git a/lib/log.h b/lib/log.h
index 7147253644..59f1742d01 100644
--- a/lib/log.h
+++ b/lib/log.h
@@ -22,8 +22,6 @@
#ifndef _ZEBRA_LOG_H
#define _ZEBRA_LOG_H
-#include "zassert.h"
-
#include <syslog.h>
#include <stdint.h>
#include <stdbool.h>
diff --git a/lib/routing_nb.c b/lib/routing_nb.c
index 0160354a7e..6238fb055d 100644
--- a/lib/routing_nb.c
+++ b/lib/routing_nb.c
@@ -16,6 +16,8 @@
* with this program; see the file COPYING; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
+#include <zebra.h>
+
#include "northbound.h"
#include "libfrr.h"
#include "routing_nb.h"
diff --git a/lib/routing_nb_config.c b/lib/routing_nb_config.c
index f66f32015d..594ad6c9e8 100644
--- a/lib/routing_nb_config.c
+++ b/lib/routing_nb_config.c
@@ -17,6 +17,8 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
+#include <zebra.h>
+
#include "northbound.h"
#include "libfrr.h"
#include "vrf.h"
diff --git a/lib/subdir.am b/lib/subdir.am
index 98ba1cf24c..480c2938d0 100644
--- a/lib/subdir.am
+++ b/lib/subdir.am
@@ -278,13 +278,14 @@ pkginclude_HEADERS += \
lib/yang.h \
lib/yang_translator.h \
lib/yang_wrappers.h \
- lib/zassert.h \
lib/zclient.h \
lib/zebra.h \
lib/zlog.h \
lib/zlog_targets.h \
lib/pbr.h \
lib/routing_nb.h \
+ \
+ lib/assert/assert.h \
# end
@@ -413,7 +414,7 @@ lib_grammar_sandbox_SOURCES = \
lib_grammar_sandbox_LDADD = \
lib/libfrr.la
-lib_clippy_CPPFLAGS = $(AM_CPPFLAGS) -D_GNU_SOURCE -DBUILDING_CLIPPY
+lib_clippy_CPPFLAGS = $(CPPFLAGS_BASE) -D_GNU_SOURCE -DBUILDING_CLIPPY
lib_clippy_CFLAGS = $(AC_CFLAGS) $(PYTHON_CFLAGS)
lib_clippy_LDADD = $(PYTHON_LIBS) $(UST_LIBS) -lelf
lib_clippy_LDFLAGS = -export-dynamic
diff --git a/lib/thread.c b/lib/thread.c
index 7b5d2f3113..3af89fad5a 100644
--- a/lib/thread.c
+++ b/lib/thread.c
@@ -664,7 +664,7 @@ static int time_hhmmss(char *buf, int buf_size, long sec)
long mm;
int wr;
- zassert(buf_size >= 8);
+ assert(buf_size >= 8);
hh = sec / 3600;
sec %= 3600;
diff --git a/lib/xref.h b/lib/xref.h
index 63166b069a..949458b313 100644
--- a/lib/xref.h
+++ b/lib/xref.h
@@ -33,6 +33,7 @@ enum xref_type {
XREFT_THREADSCHED = 0x100,
XREFT_LOGMSG = 0x200,
+ XREFT_ASSERT = 0x280,
XREFT_DEFUN = 0x300,
XREFT_INSTALL_ELEMENT = 0x301,
diff --git a/lib/zassert.h b/lib/zassert.h
deleted file mode 100644
index 527282c4f2..0000000000
--- a/lib/zassert.h
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * This file is part of Quagga.
- *
- * Quagga is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2, or (at your option) any
- * later version.
- *
- * Quagga is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; see the file COPYING; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#ifndef _QUAGGA_ASSERT_H
-#define _QUAGGA_ASSERT_H
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-extern void _zlog_assert_failed(const char *assertion, const char *file,
- unsigned int line, const char *function)
- __attribute__((noreturn));
-
-#undef __ASSERT_FUNCTION
-#define __ASSERT_FUNCTION __func__
-
-#define zassert(EX) \
- ((void)((EX) ? 0 : (_zlog_assert_failed(#EX, __FILE__, __LINE__, \
- __ASSERT_FUNCTION), \
- 0)))
-
-#undef assert
-#define assert(EX) zassert(EX)
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _QUAGGA_ASSERT_H */
diff --git a/lib/zebra.h b/lib/zebra.h
index 26c0fe05b5..3b624117de 100644
--- a/lib/zebra.h
+++ b/lib/zebra.h
@@ -206,7 +206,7 @@
#define __attribute__(x)
#endif /* !__GNUC__ || VTYSH_EXTRACT_PL */
-#include "zassert.h"
+#include <assert.h>
/*
* Add explicit static cast only when using a C++ compiler.
diff --git a/lib/zlog.c b/lib/zlog.c
index a99fd71f0d..89ab9265d1 100644
--- a/lib/zlog.c
+++ b/lib/zlog.c
@@ -526,6 +526,36 @@ void zlog_sigsafe(const char *text, size_t len)
}
}
+void _zlog_assert_failed(const struct xref_assert *xref, const char *extra, ...)
+{
+ va_list ap;
+ static bool assert_in_assert; /* "global-ish" variable, init to 0 */
+
+ if (assert_in_assert)
+ abort();
+ assert_in_assert = true;
+
+ if (extra) {
+ struct va_format vaf;
+
+ va_start(ap, extra);
+ vaf.fmt = extra;
+ vaf.va = &ap;
+
+ zlog(LOG_CRIT,
+ "%s:%d: %s(): assertion (%s) failed, extra info: %pVA",
+ xref->xref.file, xref->xref.line, xref->xref.func,
+ xref->expr, &vaf);
+
+ va_end(ap);
+ } else
+ zlog(LOG_CRIT, "%s:%d: %s(): assertion (%s) failed",
+ xref->xref.file, xref->xref.line, xref->xref.func,
+ xref->expr);
+
+ /* abort() prints backtrace & memstats in SIGABRT handler */
+ abort();
+}
int zlog_msg_prio(struct zlog_msg *msg)
{
diff --git a/lib/zlog.h b/lib/zlog.h
index 2ef4173605..c421c16f38 100644
--- a/lib/zlog.h
+++ b/lib/zlog.h
@@ -25,6 +25,8 @@
#include <unistd.h>
#include <sys/uio.h>
+#include <assert.h>
+
#include "atomlist.h"
#include "frrcu.h"
#include "memory.h"