1 /* Copyright (c) 2003, Roger Dingledine
2 * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
3 * Copyright (c) 2007-2019, The Tor Project, Inc. */
4 /* See LICENSE for licensing information */
11 #include "lib/log/util_bug.h"
12 #include "lib/log/log.h"
13 #include "lib/err/backtrace.h"
15 #include "lib/smartlist_core/smartlist_core.h"
16 #include "lib/smartlist_core/smartlist_foreach.h"
18 #include "lib/malloc/malloc.h"
19 #include "lib/string/printf.h"
24 static void (*failed_assertion_cb
)(void) = NULL
;
25 static int n_bugs_to_capture
= 0;
26 static smartlist_t
*bug_messages
= NULL
;
27 #define capturing_bugs() (bug_messages != NULL && n_bugs_to_capture)
29 tor_capture_bugs_(int n
)
31 tor_end_capture_bugs_();
32 bug_messages
= smartlist_new();
33 n_bugs_to_capture
= n
;
36 tor_end_capture_bugs_(void)
38 n_bugs_to_capture
= 0;
41 SMARTLIST_FOREACH(bug_messages
, char *, cp
, tor_free(cp
));
42 smartlist_free(bug_messages
);
46 tor_get_captured_bug_log_(void)
51 add_captured_bug(const char *s
)
54 smartlist_add_strdup(bug_messages
, s
);
56 /** Set a callback to be invoked when we get any tor_bug_occurred_
57 * invocation. We use this in the unit tests so that a nonfatal
58 * assertion failure can also count as a test failure.
61 tor_set_failed_assertion_callback(void (*fn
)(void))
63 failed_assertion_cb
= fn
;
65 #else /* !(defined(TOR_UNIT_TESTS)) */
66 #define capturing_bugs() (0)
67 #define add_captured_bug(s) do { } while (0)
68 #endif /* defined(TOR_UNIT_TESTS) */
70 /** Helper for tor_assert: report the assertion failure. */
72 tor_assertion_failed_(const char *fname
, unsigned int line
,
73 const char *func
, const char *expr
)
76 log_err(LD_BUG
, "%s:%u: %s: Assertion %s failed; aborting.",
77 fname
, line
, func
, expr
);
78 tor_snprintf(buf
, sizeof(buf
),
79 "Assertion %s failed in %s at %s:%u",
80 expr
, func
, fname
, line
);
81 log_backtrace(LOG_ERR
, LD_BUG
, buf
);
84 /** Helper for tor_assert_nonfatal: report the assertion failure. */
86 tor_bug_occurred_(const char *fname
, unsigned int line
,
87 const char *func
, const char *expr
,
91 const char *once_str
= once
?
92 " (Future instances of this warning will be silenced.)": "";
94 if (capturing_bugs()) {
95 add_captured_bug("This line should not have been reached.");
98 log_warn(LD_BUG
, "%s:%u: %s: This line should not have been reached.%s",
99 fname
, line
, func
, once_str
);
100 tor_snprintf(buf
, sizeof(buf
),
101 "Line unexpectedly reached at %s at %s:%u",
104 if (capturing_bugs()) {
105 add_captured_bug(expr
);
108 log_warn(LD_BUG
, "%s:%u: %s: Non-fatal assertion %s failed.%s",
109 fname
, line
, func
, expr
, once_str
);
110 tor_snprintf(buf
, sizeof(buf
),
111 "Non-fatal assertion %s failed in %s at %s:%u",
112 expr
, func
, fname
, line
);
114 log_backtrace(LOG_WARN
, LD_BUG
, buf
);
116 #ifdef TOR_UNIT_TESTS
117 if (failed_assertion_cb
) {
118 failed_assertion_cb();
124 /** Take a filename and return a pointer to its final element. This
125 * function is called on __FILE__ to fix a MSVC nit where __FILE__
126 * contains the full path to the file. This is bad, because it
127 * confuses users to find the home directory of the person who
128 * compiled the binary in their warning messages.
131 tor_fix_source_file(const char *fname
)
133 const char *cp1
, *cp2
, *r
;
134 cp1
= strrchr(fname
, '/');
135 cp2
= strrchr(fname
, '\\');
137 r
= (cp1
<cp2
)?(cp2
+1):(cp1
+1);
147 #endif /* defined(_WIN32) */