Tor  0.4.7.0-alpha-dev
Macros | Functions
util_bug.h File Reference

Macros to manage assertions, fatal and non-fatal. More...

#include "orconfig.h"
#include "lib/cc/compat_compiler.h"
#include "lib/log/log.h"
#include "lib/testsupport/testsupport.h"

Go to the source code of this file.

Macros

#define ASSERT_PREDICT_UNLIKELY_(e)   PREDICT_UNLIKELY(e)
 
#define ASSERT_PREDICT_LIKELY_(e)   PREDICT_LIKELY(e)
 
#define tor_assert(expr)   tor_assertf(expr, NULL)
 
#define tor_assertf(expr, fmt, ...)
 
#define tor_assert_unreached()
 
#define tor_assert_nonfatal_unreached()
 
#define tor_assert_nonfatal(cond)
 
#define tor_assertf_nonfatal(cond, fmt, ...)
 
#define tor_assert_nonfatal_unreached_once()
 
#define tor_assert_nonfatal_once(cond)
 
#define BUG(cond)
 
#define IF_BUG_ONCE__(cond, var)
 
#define IF_BUG_ONCE_VARNAME_(a)    warning_logged_on_ ## a ## __
 
#define IF_BUG_ONCE_VARNAME__(a)    IF_BUG_ONCE_VARNAME_(a)
 
#define IF_BUG_ONCE(cond)
 
#define FALLTHROUGH_UNLESS_ALL_BUGS_ARE_FATAL   FALLTHROUGH
 
#define tor_fragile_assert()   tor_assert_nonfatal_unreached_once()
 
#define SHORT_FILE__   (__FILE__)
 
#define tor_fix_source_file(s)   (s)
 

Functions

void tor_assertion_failed_ (const char *fname, unsigned int line, const char *func, const char *expr, const char *fmt,...)
 
void tor_bug_occurred_ (const char *fname, unsigned int line, const char *func, const char *expr, int once, const char *fmt,...)
 
void tor_abort_ (void) ATTR_NORETURN
 

Detailed Description

Macros to manage assertions, fatal and non-fatal.

Guidelines: All the different kinds of assertion in this file are for bug-checking only. Don't write code that can assert based on bad inputs.

We provide two kinds of assertion here: "fatal" and "nonfatal". Use nonfatal assertions for any bug you can reasonably recover from – and please, try to recover! Many severe bugs in Tor have been caused by using a regular assertion when a nonfatal assertion would have been better.

If you need to check a condition with a nonfatal assertion, AND recover from that same condition, consider using the BUG() macro inside a conditional. For example:

// wrong – use tor_assert_nonfatal() if you just want an assertion. BUG(ptr == NULL);

// okay, but needlessly verbose tor_assert_nonfatal(ptr != NULL); if (ptr == NULL) { ... }

// this is how we do it: if (BUG(ptr == NULL)) { ... }

Definition in file util_bug.h.

Macro Definition Documentation

◆ BUG

#define BUG (   cond)
Value:
(ASSERT_PREDICT_UNLIKELY_(cond) ? \
(tor_bug_occurred_(SHORT_FILE__,__LINE__,__func__,"!("#cond")",0,NULL),1) \
: 0)
void tor_bug_occurred_(const char *fname, unsigned int line, const char *func, const char *expr, int once, const char *fmt,...)
Definition: util_bug.c:106

Definition at line 207 of file util_bug.h.

◆ FALLTHROUGH_UNLESS_ALL_BUGS_ARE_FATAL

#define FALLTHROUGH_UNLESS_ALL_BUGS_ARE_FATAL   FALLTHROUGH

Use this macro after a nonfatal assertion, and before a case statement where you would want to fall through.

Definition at line 260 of file util_bug.h.

◆ IF_BUG_ONCE

#define IF_BUG_ONCE (   cond)
Value:
IF_BUG_ONCE__(ASSERT_PREDICT_UNLIKELY_(cond), \
IF_BUG_ONCE_VARNAME__(__LINE__))

This macro behaves as 'if (BUG(x))', except that it only logs its warning once, no matter how many times it triggers.

Definition at line 246 of file util_bug.h.

◆ IF_BUG_ONCE__

#define IF_BUG_ONCE__ (   cond,
  var 
)
Value:
static int var = 0; \
if ((cond) ? \
(var ? 1 : \
(var=1, \
tor_bug_occurred_(SHORT_FILE__, __LINE__, __func__, \
("!("#cond")"), 1, NULL), \
1)) \
: 0)

Definition at line 225 of file util_bug.h.

◆ tor_assert

#define tor_assert (   expr)    tor_assertf(expr, NULL)

Like assert(3), but send assertion failures to the log as well as to stderr.

Definition at line 102 of file util_bug.h.

◆ tor_assert_nonfatal

#define tor_assert_nonfatal (   cond)
Value:
STMT_BEGIN \
if (ASSERT_PREDICT_LIKELY_(cond)) { \
} else { \
tor_bug_occurred_(SHORT_FILE__, __LINE__, __func__, #cond, 0, NULL);\
} \
STMT_END

Definition at line 179 of file util_bug.h.

◆ tor_assert_nonfatal_once

#define tor_assert_nonfatal_once (   cond)
Value:
STMT_BEGIN \
static int warning_logged__ = 0; \
if (ASSERT_PREDICT_LIKELY_(cond)) { \
} else if (!warning_logged__) { \
warning_logged__ = 1; \
tor_bug_occurred_(SHORT_FILE__, __LINE__, __func__, #cond, 1, NULL);\
} \
STMT_END

Definition at line 199 of file util_bug.h.

◆ tor_assert_nonfatal_unreached

#define tor_assert_nonfatal_unreached ( )
Value:
tor_bug_occurred_(SHORT_FILE__, __LINE__, __func__, NULL, 0, NULL); \
STMT_END

Define ALL_BUGS_ARE_FATAL if you want Tor to crash when any problem comes up, so you can get a coredump and track things down.

Definition at line 176 of file util_bug.h.

◆ tor_assert_nonfatal_unreached_once

#define tor_assert_nonfatal_unreached_once ( )
Value:
STMT_BEGIN \
static int warning_logged__ = 0; \
if (!warning_logged__) { \
warning_logged__ = 1; \
tor_bug_occurred_(SHORT_FILE__, __LINE__, __func__, NULL, 1, NULL); \
} \
STMT_END

Definition at line 192 of file util_bug.h.

◆ tor_assert_unreached

#define tor_assert_unreached ( )
Value:
STMT_BEGIN { \
tor_assertion_failed_(SHORT_FILE__, __LINE__, __func__, \
"line should be unreached", NULL); \
tor_abort_(); \
} STMT_END

Definition at line 113 of file util_bug.h.

◆ tor_assertf

#define tor_assertf (   expr,
  fmt,
  ... 
)
Value:
STMT_BEGIN \
if (ASSERT_PREDICT_LIKELY_(expr)) { \
} else { \
tor_assertion_failed_(SHORT_FILE__, __LINE__, __func__, #expr, \
fmt, ##__VA_ARGS__); \
tor_abort_(); \
} STMT_END

Definition at line 104 of file util_bug.h.

◆ tor_assertf_nonfatal

#define tor_assertf_nonfatal (   cond,
  fmt,
  ... 
)
Value:
STMT_BEGIN \
if (ASSERT_PREDICT_UNLIKELY_(cond)) { \
} else { \
tor_bug_occurred_(SHORT_FILE__, __LINE__, __func__, #cond, 0, \
fmt, ##__VA_ARGS__); \
} \
STMT_END

Definition at line 185 of file util_bug.h.

◆ tor_fragile_assert

#define tor_fragile_assert ( )    tor_assert_nonfatal_unreached_once()

In older code, we used tor_fragile_assert() to mark optional failure points. At these points, we could make some debug builds fail. (But release builds would continue.)

To get the same behaviour in recent tor versions, define ALL_BUGS_ARE_FATAL, and use any non-fatal assertion or *BUG() macro.

Definition at line 270 of file util_bug.h.

Function Documentation

◆ tor_abort_()

void tor_abort_ ( void  )

Call the tor_raw_abort_() function to close raw logs, then kill the current process with a fatal error. But first, close the file-based log file descriptors, so error messages are written before process termination.

(This is a separate function so that we declare it in util_bug.h without including torerr.h in all the users of util_bug.h)

Definition at line 171 of file util_bug.c.

◆ tor_assertion_failed_()

void tor_assertion_failed_ ( const char *  fname,
unsigned int  line,
const char *  func,
const char *  expr,
const char *  fmt,
  ... 
)

Helper for tor_assert: report the assertion failure.

Definition at line 74 of file util_bug.c.

◆ tor_bug_occurred_()

void tor_bug_occurred_ ( const char *  fname,
unsigned int  line,
const char *  func,
const char *  expr,
int  once,
const char *  fmt,
  ... 
)

Helper for tor_assert_nonfatal: report the assertion failure.

Definition at line 106 of file util_bug.c.