tor  0.4.2.0-alpha-dev
util_bug.c
Go to the documentation of this file.
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 */
5 
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
17 #endif
18 #include "lib/malloc/malloc.h"
19 #include "lib/string/printf.h"
20 
21 #include <string.h>
22 #include <stdlib.h>
23 
24 #ifdef TOR_UNIT_TESTS
25 static void (*failed_assertion_cb)(void) = NULL;
26 static int n_bugs_to_capture = 0;
27 static smartlist_t *bug_messages = NULL;
28 #define capturing_bugs() (bug_messages != NULL && n_bugs_to_capture)
29 void
30 tor_capture_bugs_(int n)
31 {
32  tor_end_capture_bugs_();
33  bug_messages = smartlist_new();
34  n_bugs_to_capture = n;
35 }
36 void
37 tor_end_capture_bugs_(void)
38 {
39  n_bugs_to_capture = 0;
40  if (!bug_messages)
41  return;
42  SMARTLIST_FOREACH(bug_messages, char *, cp, tor_free(cp));
43  smartlist_free(bug_messages);
44  bug_messages = NULL;
45 }
46 const smartlist_t *
47 tor_get_captured_bug_log_(void)
48 {
49  return bug_messages;
50 }
51 static void
52 add_captured_bug(const char *s)
53 {
54  --n_bugs_to_capture;
55  smartlist_add_strdup(bug_messages, s);
56 }
61 void
62 tor_set_failed_assertion_callback(void (*fn)(void))
63 {
64  failed_assertion_cb = fn;
65 }
66 #else /* !(defined(TOR_UNIT_TESTS)) */
67 #define capturing_bugs() (0)
68 #define add_captured_bug(s) do { } while (0)
69 #endif /* defined(TOR_UNIT_TESTS) */
70 
72 void
73 CHECK_PRINTF(5, 6)
74 tor_assertion_failed_(const char *fname, unsigned int line,
75  const char *func, const char *expr,
76  const char *fmt, ...)
77 {
78  char *buf = NULL;
79  char *extra = NULL;
80  va_list ap;
81 
82 #ifdef __clang__
83 #pragma clang diagnostic push
84 #pragma clang diagnostic ignored "-Wformat-nonliteral"
85 #endif
86  if (fmt) {
87  va_start(ap,fmt);
88  tor_vasprintf(&extra, fmt, ap);
89  va_end(ap);
90  }
91 #ifdef __clang__
92 #pragma clang diagnostic pop
93 #endif
94 
95  log_err(LD_BUG, "%s:%u: %s: Assertion %s failed; aborting.",
96  fname, line, func, expr);
97  tor_asprintf(&buf, "Assertion %s failed in %s at %s:%u: %s",
98  expr, func, fname, line, extra ? extra : "");
99  tor_free(extra);
100  log_backtrace(LOG_ERR, LD_BUG, buf);
101  tor_free(buf);
102 }
103 
105 void
106 CHECK_PRINTF(6, 7)
107 tor_bug_occurred_(const char *fname, unsigned int line,
108  const char *func, const char *expr,
109  int once, const char *fmt, ...)
110 {
111  char *buf = NULL;
112  const char *once_str = once ?
113  " (Future instances of this warning will be silenced.)": "";
114  if (! expr) {
115  if (capturing_bugs()) {
116  add_captured_bug("This line should not have been reached.");
117  return;
118  }
119  log_warn(LD_BUG, "%s:%u: %s: This line should not have been reached.%s",
120  fname, line, func, once_str);
121  tor_asprintf(&buf,
122  "Line unexpectedly reached at %s at %s:%u",
123  func, fname, line);
124  } else {
125  if (capturing_bugs()) {
126  add_captured_bug(expr);
127  return;
128  }
129 
130  va_list ap;
131  char *extra = NULL;
132 
133 #ifdef __clang__
134 #pragma clang diagnostic push
135 #pragma clang diagnostic ignored "-Wformat-nonliteral"
136 #endif
137  if (fmt) {
138  va_start(ap,fmt);
139  tor_vasprintf(&extra, fmt, ap);
140  va_end(ap);
141  }
142 #ifdef __clang__
143 #pragma clang diagnostic pop
144 #endif
145 
146  log_warn(LD_BUG, "%s:%u: %s: Non-fatal assertion %s failed.%s",
147  fname, line, func, expr, once_str);
148  tor_asprintf(&buf, "Non-fatal assertion %s failed in %s at %s:%u%s%s",
149  expr, func, fname, line, fmt ? " : " : "",
150  extra ? extra : "");
151  tor_free(extra);
152  }
153  log_backtrace(LOG_WARN, LD_BUG, buf);
154  tor_free(buf);
155 
156 #ifdef TOR_UNIT_TESTS
157  if (failed_assertion_cb) {
158  failed_assertion_cb();
159  }
160 #endif
161 }
162 
170 void
172 {
173  abort();
174 }
175 
176 #ifdef _WIN32
177 
183 const char *
184 tor_fix_source_file(const char *fname)
185 {
186  const char *cp1, *cp2, *r;
187  cp1 = strrchr(fname, '/');
188  cp2 = strrchr(fname, '\\');
189  if (cp1 && cp2) {
190  r = (cp1<cp2)?(cp2+1):(cp1+1);
191  } else if (cp1) {
192  r = cp1+1;
193  } else if (cp2) {
194  r = cp2+1;
195  } else {
196  r = fname;
197  }
198  return r;
199 }
200 #endif /* defined(_WIN32) */
Header for printf.c.
Header for backtrace.c.
void smartlist_add_strdup(struct smartlist_t *sl, const char *string)
int tor_vasprintf(char **strp, const char *fmt, va_list args)
Definition: printf.c:96
#define tor_free(p)
Definition: malloc.h:52
Headers for util_malloc.c.
Top-level declarations for the smartlist_t dynamic array type.
void tor_abort_(void)
Definition: util_bug.c:171
Macros for iterating over the elements of a smartlist_t.
int tor_asprintf(char **strp, const char *fmt,...)
Definition: printf.c:75
void tor_assertion_failed_(const char *fname, unsigned int line, const char *func, const char *expr, const char *fmt,...)
Definition: util_bug.c:74
#define LOG_WARN
Definition: log.h:50
#define LOG_ERR
Definition: log.h:53
#define SMARTLIST_FOREACH(sl, type, var, cmd)
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:107
Headers for log.c.
Macros to manage assertions, fatal and non-fatal.
#define LD_BUG
Definition: log.h:83