1 /* Error handling and debugging stuff */
4 #define _GNU_SOURCE /* Needed for vasprintf() */
20 #ifdef HAVE_SYS_TIME_H
29 #include "util/error.h"
30 #include "util/lists.h"
31 #include "util/memlist.h"
32 #include "util/memory.h"
33 #include "util/snprintf.h"
34 #include "util/string.h"
37 unsigned char full_static_version
[1024] = "ELinks " VERSION_STRING
;
40 er(int bell
, int shall_sleep
, unsigned char *fmt
, va_list params
)
43 #ifdef CONFIG_OS_WIN32
44 MessageBeep(MB_ICONEXCLAMATION
);
46 fputc(7, stderr
); /* load and annoying on Windows */
48 vfprintf(stderr
, fmt
, params
);
51 if (shall_sleep
) sleep(1);
55 unsigned char *errfile
;
58 elinks_debug(unsigned char *fmt
, ...)
60 unsigned char errbuf
[4096];
63 va_start(params
, fmt
);
65 snprintf(errbuf
, sizeof(errbuf
), "DEBUG MESSAGE at %s:%d: %s",
66 errfile
, errline
, fmt
);
68 er(0, 0, errbuf
, params
);
74 elinks_wdebug(unsigned char *fmt
, ...)
76 unsigned char errbuf
[4096];
79 va_start(params
, fmt
);
81 snprintf(errbuf
, sizeof(errbuf
), "DEBUG MESSAGE at %s:%d: %s",
82 errfile
, errline
, fmt
);
84 er(0, 1, errbuf
, params
);
90 elinks_error(unsigned char *fmt
, ...)
92 unsigned char errbuf
[4096];
95 va_start(params
, fmt
);
97 snprintf(errbuf
, sizeof(errbuf
), "ERROR at %s:%d: %s",
98 errfile
, errline
, fmt
);
100 er(1, 1, errbuf
, params
);
106 elinks_internal(unsigned char *fmt
, ...)
108 unsigned char errbuf
[4096];
111 va_start(params
, fmt
);
113 snprintf(errbuf
, sizeof(errbuf
),
114 "\033[1mINTERNAL ERROR\033[0m at %s:%d: %s",
115 errfile
, errline
, fmt
);
117 er(1, 1, errbuf
, params
);
127 usrerror(unsigned char *fmt
, ...)
131 va_start(params
, fmt
);
133 fputs("ELinks: ", stderr
);
134 vfprintf(stderr
, fmt
, params
);
142 int assert_failed
= 0;
145 elinks_assertm(int x
, unsigned char *fmt
, ...)
147 unsigned char *buf
= NULL
;
150 if (assert_failed
) return;
151 if (!(assert_failed
= !x
)) return;
153 va_start(params
, fmt
);
154 vasprintf((char **) &buf
, fmt
, params
);
156 elinks_internal("assertion failed: %s", buf
);
166 "\n\033[1m%s\033[0m %s\n", "Forcing core dump!",
167 "Man the Lifeboats! Women and children first!\n");
168 fputs("But please DO NOT report this as a segfault!!! It is an internal error, not a\n"
169 "normal segfault, there is a huge difference in these for us the developers.\n"
170 "Also, noting the EXACT error you got above is crucial for hunting the problem\n"
171 "down. Thanks, and please get in touch with us.\n",
173 #ifndef CONFIG_BACKTRACE
174 fputs(full_static_version
, stderr
);
181 static FILE *log_file
= NULL
;
186 unsigned char errbuf
[4096];
187 time_t curtime
= time(NULL
);
188 struct tm
*loctime
= localtime(&curtime
);
191 len
= strftime(errbuf
, sizeof(errbuf
), "%a, %d %b %Y %H:%M:%S %z",
195 fprintf(log_file
, "[%-5s %-15s %4s]: Log stopped at %s\n\n\n",
202 elinks_log(unsigned char *msg
, unsigned char *file
, int line
,
203 unsigned char *fmt
, ...)
205 static unsigned char *log_files
= NULL
;
206 static unsigned char *log_msg
= NULL
;
207 unsigned char errbuf
[4096];
211 unsigned char *log_name
;
212 time_t curtime
= time(NULL
);
213 struct tm
*loctime
= localtime(&curtime
);
216 log_files
= getenv("ELINKS_FILES");
217 log_msg
= getenv("ELINKS_MSG");
218 log_name
= getenv("ELINKS_LOG");
219 log_file
= log_name
? fopen(log_name
, "ab") : stderr
;
221 if (!log_file
) return;
223 len
= strftime(errbuf
, sizeof(errbuf
), "%a, %d %b %Y %H:%M:%S %z",
227 fprintf(log_file
, "\n\n[%-5s %-15s %4s]: Log started at %s\n",
228 "type", "file", "line", errbuf
);
233 if (log_files
&& !strstr(log_files
, file
))
236 if (log_msg
&& !strstr(log_msg
, msg
))
239 va_start(params
, fmt
);
241 snprintf(errbuf
, sizeof(errbuf
), "[%-5s %-15s %4d]: %s",
242 msg
, file
, line
, fmt
);
244 vfprintf(log_file
, errbuf
, params
);
245 fputc('\n', log_file
);
254 do_not_optimize_here(void *p
)
256 /* stop GCC optimization - avoid bugs in it */
260 #ifdef CONFIG_BACKTRACE
262 /* The backtrace corner. */
267 #ifdef HAVE_EXECINFO_H
268 #include <execinfo.h>
272 dump_backtrace(FILE *f
, int trouble
)
274 /* If trouble is set, when we get here, we can be in various
275 * interesting situations like inside of the SIGSEGV handler etc. So be
276 * especially careful here. Dynamic memory allocation may not work
277 * (corrupted stack). A lot of other things may not work too. So better
278 * don't do anything not 100% necessary. */
280 #ifdef HAVE_EXECINFO_H
281 /* glibc way of doing this */
288 size
= backtrace(stack
, 20);
291 /* Let's hope fileno() is safe. */
292 backtrace_symbols_fd(stack
, size
, fileno(f
));
297 strings
= backtrace_symbols(stack
, size
);
299 fprintf(f
, "Obtained %d stack frames:\n", (int) size
);
301 for (i
= 0; i
< size
; i
++)
302 fprintf(f
, "[%p] %s\n", stack
[i
], strings
[i
]);
307 /* User torturation. */
308 /* You are worried about what you see here? You don't see anything in
309 * the first place. Also, be assured that we know what are we doing. */
310 /* (We are killing the user, obviously.) */
312 /* TODO: Gettextify? Er, better not. More people (translators) could
313 * find out what are we doing... ;-) --pasky */
314 /* TODO: Be more cruel when in trouble? ;-) --pasky */
316 fputs( "Wheeeeeeeeeee! You played with the config.h by hand, didn't you?\n"
317 "Of _COURSE_ you did! Is that how a nice .. creature behaves like?\n"
318 "Of _COURSE_ it isn't! I feel offended and thus I will revenge now!\n"
319 "You will _suffer_ >:).\n"
321 "CPU burning sequence initiated...\n", f
);
323 /* TODO: Include cpuburn.c here. --pasky */