* Added better handling of SIGBUS, including the error type and fault address in the dump.

git-svn-id: svn://rakshasa.no/libtorrent/trunk/rtorrent@1247 e378c898-3ddf-0310-93e7-cc216c733640
This commit is contained in:
rakshasa
2011-07-20 09:57:29 +00:00
parent f5d4924b22
commit fa8ef65cd7
3 changed files with 74 additions and 1 deletions
+53 -1
View File
@@ -44,6 +44,7 @@
#include <torrent/torrent.h>
#include <torrent/exceptions.h>
#include <rak/functional.h>
#include <rak/error_number.h>
#ifdef USE_EXECINFO
#include <execinfo.h>
@@ -73,6 +74,7 @@
#include "thread_main.h"
#include "thread_worker.h"
void handle_sigbus(int signum, siginfo_t* sa, void* ptr);
void do_panic(int signum);
void print_help();
void initialize_commands();
@@ -178,9 +180,10 @@ main(int argc, char** argv) {
SignalHandler::set_handler(SIGWINCH, sigc::mem_fun(control->display(), &display::Manager::force_redraw));
SignalHandler::set_handler(SIGSEGV, sigc::bind(sigc::ptr_fun(&do_panic), SIGSEGV));
SignalHandler::set_handler(SIGILL, sigc::bind(sigc::ptr_fun(&do_panic), SIGILL));
SignalHandler::set_handler(SIGBUS, sigc::bind(sigc::ptr_fun(&do_panic), SIGBUS));
SignalHandler::set_handler(SIGFPE, sigc::bind(sigc::ptr_fun(&do_panic), SIGFPE));
SignalHandler::set_sigaction_handler(SIGBUS, &handle_sigbus);
// SIGUSR1 is used for interrupting polling, forcing that thread
// to process new non-socket events.
SignalHandler::set_handler(SIGUSR1, sigc::ptr_fun(&do_nothing));
@@ -877,6 +880,55 @@ main(int argc, char** argv) {
return 0;
}
void
handle_sigbus(int signum, siginfo_t* sa, void* ptr) {
if (signum != SIGBUS)
do_panic(signum);
SignalHandler::set_default(signum);
display::Canvas::cleanup();
// Use printf here instead...
printf("Caught SIGBUS, dumping stack:\n");
#ifdef USE_EXECINFO
void* stackPtrs[20];
// Print the stack and exit.
int stackSize = backtrace(stackPtrs, 20);
char** stackStrings = backtrace_symbols(stackPtrs, stackSize);
for (int i = 0; i < stackSize; ++i)
printf("%i %s\n", i, stackStrings[i]);
#else
printf("Stack dump not enabled.\n");
#endif
printf("\nError: %s\n", rak::error_number::error_number(sa->si_errno).c_str());
const char* signal_reason;
switch (sa->si_code) {
case BUS_ADRALN: signal_reason = "Invalid address alignment."; break;
case BUS_ADRERR: signal_reason = "Non-existent physical address."; break;
case BUS_OBJERR: signal_reason = "Object specific hardware error."; break;
default:
if (sa->si_code <= 0)
signal_reason = "User-generated signal.";
else
signal_reason = "Unknown.";
break;
};
printf("Signal code '%i': %s\n", sa->si_code, signal_reason);
printf("Fault address: %p.\n", sa->si_addr);
std::abort();
}
void
do_panic(int signum) {
// Use the default signal handler in the future to avoid infinit