mirror of
https://github.com/rakshasa/rtorrent.git
synced 2026-10-21 00:26:16 +00:00
* 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:
+53
-1
@@ -44,6 +44,7 @@
|
|||||||
#include <torrent/torrent.h>
|
#include <torrent/torrent.h>
|
||||||
#include <torrent/exceptions.h>
|
#include <torrent/exceptions.h>
|
||||||
#include <rak/functional.h>
|
#include <rak/functional.h>
|
||||||
|
#include <rak/error_number.h>
|
||||||
|
|
||||||
#ifdef USE_EXECINFO
|
#ifdef USE_EXECINFO
|
||||||
#include <execinfo.h>
|
#include <execinfo.h>
|
||||||
@@ -73,6 +74,7 @@
|
|||||||
#include "thread_main.h"
|
#include "thread_main.h"
|
||||||
#include "thread_worker.h"
|
#include "thread_worker.h"
|
||||||
|
|
||||||
|
void handle_sigbus(int signum, siginfo_t* sa, void* ptr);
|
||||||
void do_panic(int signum);
|
void do_panic(int signum);
|
||||||
void print_help();
|
void print_help();
|
||||||
void initialize_commands();
|
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(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(SIGSEGV, sigc::bind(sigc::ptr_fun(&do_panic), SIGSEGV));
|
||||||
SignalHandler::set_handler(SIGILL, sigc::bind(sigc::ptr_fun(&do_panic), SIGILL));
|
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_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
|
// SIGUSR1 is used for interrupting polling, forcing that thread
|
||||||
// to process new non-socket events.
|
// to process new non-socket events.
|
||||||
SignalHandler::set_handler(SIGUSR1, sigc::ptr_fun(&do_nothing));
|
SignalHandler::set_handler(SIGUSR1, sigc::ptr_fun(&do_nothing));
|
||||||
@@ -877,6 +880,55 @@ main(int argc, char** argv) {
|
|||||||
return 0;
|
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
|
void
|
||||||
do_panic(int signum) {
|
do_panic(int signum) {
|
||||||
// Use the default signal handler in the future to avoid infinit
|
// Use the default signal handler in the future to avoid infinit
|
||||||
|
|||||||
@@ -36,7 +36,9 @@
|
|||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
|
||||||
|
#include <signal.h>
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
|
#include "rak/error_number.h"
|
||||||
#include "signal_handler.h"
|
#include "signal_handler.h"
|
||||||
|
|
||||||
SignalHandler::Slot SignalHandler::m_handlers[HIGHEST_SIGNAL];
|
SignalHandler::Slot SignalHandler::m_handlers[HIGHEST_SIGNAL];
|
||||||
@@ -71,6 +73,20 @@ SignalHandler::set_handler(unsigned int signum, Slot slot) {
|
|||||||
m_handlers[signum] = slot;
|
m_handlers[signum] = slot;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
SignalHandler::set_sigaction_handler(unsigned int signum, handler_slot slot) {
|
||||||
|
if (signum > HIGHEST_SIGNAL)
|
||||||
|
throw std::logic_error("SignalHandler::set_handler(...) received invalid signal value.");
|
||||||
|
|
||||||
|
struct sigaction sa;
|
||||||
|
sa.sa_sigaction = slot;
|
||||||
|
sa.sa_mask = 0;
|
||||||
|
sa.sa_flags = SA_SIGINFO;
|
||||||
|
|
||||||
|
if (sigaction(signum, &sa, NULL) == -1)
|
||||||
|
throw std::logic_error("Could not set sigaction: " + std::string(rak::error_number::current().c_str()));
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
SignalHandler::caught(int signum) {
|
SignalHandler::caught(int signum) {
|
||||||
if ((unsigned)signum > HIGHEST_SIGNAL)
|
if ((unsigned)signum > HIGHEST_SIGNAL)
|
||||||
|
|||||||
@@ -44,6 +44,9 @@ class SignalHandler {
|
|||||||
public:
|
public:
|
||||||
typedef sigc::slot0<void> Slot;
|
typedef sigc::slot0<void> Slot;
|
||||||
|
|
||||||
|
// typedef void (*handler_slot)(int, siginfo_t *info, ucontext_t *uap);
|
||||||
|
typedef void (*handler_slot)(int, siginfo_t*, void*);
|
||||||
|
|
||||||
#ifdef NSIG
|
#ifdef NSIG
|
||||||
static const unsigned int HIGHEST_SIGNAL = NSIG;
|
static const unsigned int HIGHEST_SIGNAL = NSIG;
|
||||||
#else
|
#else
|
||||||
@@ -55,6 +58,8 @@ public:
|
|||||||
static void set_ignore(unsigned int signum);
|
static void set_ignore(unsigned int signum);
|
||||||
static void set_handler(unsigned int signum, Slot slot);
|
static void set_handler(unsigned int signum, Slot slot);
|
||||||
|
|
||||||
|
static void set_sigaction_handler(unsigned int signum, handler_slot slot);
|
||||||
|
|
||||||
static const char* as_string(unsigned int signum);
|
static const char* as_string(unsigned int signum);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|||||||
Reference in New Issue
Block a user