Bump copyright date to 2019
[tor.git] / src / lib / log / util_bug.c
blobf42d2d2ab43286f542af9eaa85a2cbbcb5ffa793
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 */
6 /**
7 * \file util_bug.c
8 **/
10 #include "orconfig.h"
11 #include "lib/log/util_bug.h"
12 #include "lib/log/log.h"
13 #include "lib/err/backtrace.h"
14 #ifdef TOR_UNIT_TESTS
15 #include "lib/smartlist_core/smartlist_core.h"
16 #include "lib/smartlist_core/smartlist_foreach.h"
17 #endif
18 #include "lib/malloc/malloc.h"
19 #include "lib/string/printf.h"
21 #include <string.h>
23 #ifdef TOR_UNIT_TESTS
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)
28 void
29 tor_capture_bugs_(int n)
31 tor_end_capture_bugs_();
32 bug_messages = smartlist_new();
33 n_bugs_to_capture = n;
35 void
36 tor_end_capture_bugs_(void)
38 n_bugs_to_capture = 0;
39 if (!bug_messages)
40 return;
41 SMARTLIST_FOREACH(bug_messages, char *, cp, tor_free(cp));
42 smartlist_free(bug_messages);
43 bug_messages = NULL;
45 const smartlist_t *
46 tor_get_captured_bug_log_(void)
48 return bug_messages;
50 static void
51 add_captured_bug(const char *s)
53 --n_bugs_to_capture;
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.
60 void
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. */
71 void
72 tor_assertion_failed_(const char *fname, unsigned int line,
73 const char *func, const char *expr)
75 char buf[256];
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. */
85 void
86 tor_bug_occurred_(const char *fname, unsigned int line,
87 const char *func, const char *expr,
88 int once)
90 char buf[256];
91 const char *once_str = once ?
92 " (Future instances of this warning will be silenced.)": "";
93 if (! expr) {
94 if (capturing_bugs()) {
95 add_captured_bug("This line should not have been reached.");
96 return;
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",
102 func, fname, line);
103 } else {
104 if (capturing_bugs()) {
105 add_captured_bug(expr);
106 return;
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();
120 #endif
123 #ifdef _WIN32
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.
130 const char *
131 tor_fix_source_file(const char *fname)
133 const char *cp1, *cp2, *r;
134 cp1 = strrchr(fname, '/');
135 cp2 = strrchr(fname, '\\');
136 if (cp1 && cp2) {
137 r = (cp1<cp2)?(cp2+1):(cp1+1);
138 } else if (cp1) {
139 r = cp1+1;
140 } else if (cp2) {
141 r = cp2+1;
142 } else {
143 r = fname;
145 return r;
147 #endif /* defined(_WIN32) */