1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
|
/* Copyright (c) 2003, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
* Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
* \file util_bug.c
**/
#include "orconfig.h"
#include "util_bug.h"
#include "torlog.h"
#include "backtrace.h"
#include "container.h"
#ifdef __COVERITY__
int bug_macro_deadcode_dummy__ = 0;
#endif
#ifdef TOR_UNIT_TESTS
static void (*failed_assertion_cb)(void) = NULL;
static int n_bugs_to_capture = 0;
static smartlist_t *bug_messages = NULL;
#define capturing_bugs() (bug_messages != NULL && n_bugs_to_capture)
void
tor_capture_bugs_(int n)
{
tor_end_capture_bugs_();
bug_messages = smartlist_new();
n_bugs_to_capture = n;
}
void
tor_end_capture_bugs_(void)
{
n_bugs_to_capture = 0;
if (!bug_messages)
return;
SMARTLIST_FOREACH(bug_messages, char *, cp, tor_free(cp));
smartlist_free(bug_messages);
bug_messages = NULL;
}
const smartlist_t *
tor_get_captured_bug_log_(void)
{
return bug_messages;
}
static void
add_captured_bug(const char *s)
{
--n_bugs_to_capture;
smartlist_add_strdup(bug_messages, s);
}
/** Set a callback to be invoked when we get any tor_bug_occurred_
* invocation. We use this in the unit tests so that a nonfatal
* assertion failure can also count as a test failure.
*/
void
tor_set_failed_assertion_callback(void (*fn)(void))
{
failed_assertion_cb = fn;
}
#else /* !(defined(TOR_UNIT_TESTS)) */
#define capturing_bugs() (0)
#define add_captured_bug(s) do { } while (0)
#endif /* defined(TOR_UNIT_TESTS) */
/** Helper for tor_assert: report the assertion failure. */
void
tor_assertion_failed_(const char *fname, unsigned int line,
const char *func, const char *expr)
{
char buf[256];
log_err(LD_BUG, "%s:%u: %s: Assertion %s failed; aborting.",
fname, line, func, expr);
tor_snprintf(buf, sizeof(buf),
"Assertion %s failed in %s at %s:%u",
expr, func, fname, line);
log_backtrace(LOG_ERR, LD_BUG, buf);
}
/** Helper for tor_assert_nonfatal: report the assertion failure. */
void
tor_bug_occurred_(const char *fname, unsigned int line,
const char *func, const char *expr,
int once)
{
char buf[256];
const char *once_str = once ?
" (Future instances of this warning will be silenced.)": "";
if (! expr) {
if (capturing_bugs()) {
add_captured_bug("This line should not have been reached.");
return;
}
log_warn(LD_BUG, "%s:%u: %s: This line should not have been reached.%s",
fname, line, func, once_str);
tor_snprintf(buf, sizeof(buf),
"Line unexpectedly reached at %s at %s:%u",
func, fname, line);
} else {
if (capturing_bugs()) {
add_captured_bug(expr);
return;
}
log_warn(LD_BUG, "%s:%u: %s: Non-fatal assertion %s failed.%s",
fname, line, func, expr, once_str);
tor_snprintf(buf, sizeof(buf),
"Non-fatal assertion %s failed in %s at %s:%u",
expr, func, fname, line);
}
log_backtrace(LOG_WARN, LD_BUG, buf);
#ifdef TOR_UNIT_TESTS
if (failed_assertion_cb) {
failed_assertion_cb();
}
#endif
}
|