mirror of
https://github.com/openvswitch/ovs
synced 2025-10-27 15:18:06 +00:00
util: Introduce ovs_assert macro.
An occasionally significant problem with the standard "assert" macro is that it writes the failure message to stderr. In our daemons, stderr is generally redirected to /dev/null. It's more useful to write the failure message to the log, which is what the new ovs_assert macro introduced in this patch does. Signed-off-by: Ben Pfaff <blp@nicira.com> Acked-by: Ethan Jackson <ethan@nicira.com>
This commit is contained in:
@@ -26,6 +26,8 @@
|
||||
#define ALWAYS_INLINE __attribute__((always_inline))
|
||||
#define WARN_UNUSED_RESULT __attribute__((__warn_unused_result__))
|
||||
#define SENTINEL(N) __attribute__((sentinel(N)))
|
||||
#define OVS_LIKELY(CONDITION) __builtin_expect(!!(CONDITION), 1)
|
||||
#define OVS_UNLIKELY(CONDITION) __builtin_expect(!!(CONDITION), 0)
|
||||
#else
|
||||
#define NO_RETURN
|
||||
#define OVS_UNUSED
|
||||
@@ -35,6 +37,8 @@
|
||||
#define ALWAYS_INLINE
|
||||
#define WARN_UNUSED_RESULT
|
||||
#define SENTINEL(N)
|
||||
#define OVS_LIKELY(CONDITION) (!!(CONDITION))
|
||||
#define OVS_UNLIKELY(CONDITION) (!!(CONDITION))
|
||||
#endif
|
||||
|
||||
/* ISO C says that a C implementation may choose any integer type for an enum
|
||||
|
||||
29
lib/util.c
29
lib/util.c
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2008, 2009, 2010, 2011, 2012 Nicira, Inc.
|
||||
* Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013 Nicira, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -16,7 +16,6 @@
|
||||
|
||||
#include <config.h>
|
||||
#include "util.h"
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <limits.h>
|
||||
#include <stdarg.h>
|
||||
@@ -45,6 +44,30 @@ const char *subprogram_name = "";
|
||||
/* --version option output. */
|
||||
static char *program_version;
|
||||
|
||||
void
|
||||
ovs_assert_failure(const char *where, const char *function,
|
||||
const char *condition)
|
||||
{
|
||||
/* Prevent an infinite loop (or stack overflow) in case VLOG_ABORT happens
|
||||
* to trigger an assertion failure of its own. */
|
||||
static int reentry = 0;
|
||||
|
||||
switch (reentry++) {
|
||||
case 0:
|
||||
VLOG_ABORT("%s: assertion %s failed in %s()",
|
||||
where, condition, function);
|
||||
NOT_REACHED();
|
||||
|
||||
case 1:
|
||||
fprintf(stderr, "%s: assertion %s failed in %s()",
|
||||
where, condition, function);
|
||||
abort();
|
||||
|
||||
default:
|
||||
abort();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
out_of_memory(void)
|
||||
{
|
||||
@@ -756,7 +779,7 @@ english_list_delimiter(size_t index, size_t total)
|
||||
int
|
||||
log_2_floor(uint32_t n)
|
||||
{
|
||||
assert(n);
|
||||
ovs_assert(n);
|
||||
|
||||
#if !defined(UINT_MAX) || !defined(UINT32_MAX)
|
||||
#error "Someone screwed up the #includes."
|
||||
|
||||
11
lib/util.h
11
lib/util.h
@@ -62,6 +62,17 @@
|
||||
#define BUILD_ASSERT_DECL_GCCONLY(EXPR) ((void) 0)
|
||||
#endif
|
||||
|
||||
/* Like the standard assert macro, except:
|
||||
*
|
||||
* - Writes the failure message to the log.
|
||||
*
|
||||
* - Not affected by NDEBUG. */
|
||||
#define ovs_assert(CONDITION) \
|
||||
if (!OVS_LIKELY(CONDITION)) { \
|
||||
ovs_assert_failure(SOURCE_LOCATOR, __func__, #CONDITION); \
|
||||
}
|
||||
void ovs_assert_failure(const char *, const char *, const char *) NO_RETURN;
|
||||
|
||||
/* Casts 'pointer' to 'type' and issues a compiler warning if the cast changes
|
||||
* anything other than an outermost "const" or "volatile" qualifier.
|
||||
*
|
||||
|
||||
@@ -140,3 +140,22 @@ mkdir 01234567890123456789012345678901234567890123456789012345678901234567890123
|
||||
cd 012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
|
||||
AT_CHECK([test-unix-socket ../012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789/socket socket])
|
||||
AT_CLEANUP
|
||||
|
||||
AT_SETUP([ovs_assert])
|
||||
OVS_LOGDIR=`pwd`; export OVS_LOGDIR
|
||||
AT_CHECK([test-util -voff -vfile:info '-vPATTERN:file:%c|%p|%m' --log-file assert || kill -l $?],
|
||||
[0], [ABRT
|
||||
], [stderr])
|
||||
|
||||
AT_CHECK([sed 's/\(opened log file\) .*/\1/
|
||||
s/|[[^|]]*: /|/' test-util.log], [0], [dnl
|
||||
vlog|INFO|opened log file
|
||||
util|EMER|assertion false failed in test_assert()
|
||||
])
|
||||
|
||||
AT_CHECK([sed 's/.*: //
|
||||
1q' stderr], [0],
|
||||
[assertion false failed in test_assert()
|
||||
])
|
||||
|
||||
AT_CLEANUP
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include <getopt.h>
|
||||
#include <inttypes.h>
|
||||
#include <limits.h>
|
||||
#include <stdio.h>
|
||||
@@ -25,6 +26,7 @@
|
||||
#include "command-line.h"
|
||||
#include "random.h"
|
||||
#include "util.h"
|
||||
#include "vlog.h"
|
||||
|
||||
#undef NDEBUG
|
||||
#include <assert.h>
|
||||
@@ -335,6 +337,12 @@ test_follow_symlinks(int argc, char *argv[])
|
||||
free(target);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
test_assert(int argc OVS_UNUSED, char *argv[] OVS_UNUSED)
|
||||
{
|
||||
ovs_assert(false);
|
||||
}
|
||||
|
||||
static const struct command commands[] = {
|
||||
{"ctz", 0, 0, test_ctz},
|
||||
@@ -345,13 +353,46 @@ static const struct command commands[] = {
|
||||
{"bitwise_one", 0, 0, test_bitwise_one},
|
||||
{"bitwise_is_all_zeros", 0, 0, test_bitwise_is_all_zeros},
|
||||
{"follow-symlinks", 1, INT_MAX, test_follow_symlinks},
|
||||
{"assert", 0, 0, test_assert},
|
||||
{NULL, 0, 0, NULL},
|
||||
};
|
||||
|
||||
static void
|
||||
parse_options(int argc, char *argv[])
|
||||
{
|
||||
enum {
|
||||
VLOG_OPTION_ENUMS
|
||||
};
|
||||
static struct option long_options[] = {
|
||||
VLOG_LONG_OPTIONS,
|
||||
{NULL, 0, NULL, 0},
|
||||
};
|
||||
char *short_options = long_options_to_short_options(long_options);
|
||||
|
||||
for (;;) {
|
||||
int c = getopt_long(argc, argv, short_options, long_options, NULL);
|
||||
if (c == -1) {
|
||||
break;
|
||||
}
|
||||
|
||||
switch (c) {
|
||||
VLOG_OPTION_HANDLERS
|
||||
|
||||
case '?':
|
||||
exit(EXIT_FAILURE);
|
||||
|
||||
default:
|
||||
abort();
|
||||
}
|
||||
}
|
||||
free(short_options);
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
set_program_name(argv[0]);
|
||||
run_command(argc - 1, argv + 1, commands);
|
||||
parse_options(argc, argv);
|
||||
run_command(argc - optind, argv + optind, commands);
|
||||
return 0;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user