# # This patch adds an automatic backtrace to internal errors in # libtorrent/rtorrent, on systems that support backtrace(). # # After applying the patch, you must run autogen.sh for both # libtorrent and rtorrent. # # To make it useful, you must configure libtorrent and rtorrent # with "-rdynamic" in the LDFLAGS. Unless you have other LDFLAGS # you need to use, configure both like this: # ./configure LDFLAGS=-rdynamic # Of course add any other options you need in addition. # # After configuring each, check for the following line: # "checking for execinfo.h... yes". # Also, config.h should have "#define USE_EXECINFO 1" # # If it does not, your system probably doesn't support backtrace() # and so this patch will be useless. # # ================================================================= Index: rtorrent/src/main.cc =================================================================== --- rtorrent/src/main.cc (revision 1105) +++ rtorrent/src/main.cc (working copy) @@ -324,6 +324,19 @@ control->core()->download_list()->session_save(); control->cleanup(); +#ifdef USE_EXECINFO + } catch (torrent::internal_error& e) { + control->cleanup_exception(); + + std::cout << "rtorrent: " << e.what() << std::endl; + char** stackStrings = backtrace_symbols(e.get_stack(), e.stack_size()); + + for (int i = 0; i < e.stack_size(); ++i) + std::cout << i << ' ' << stackStrings[i] << std::endl; + + return -1; +#endif + } catch (std::exception& e) { control->cleanup_exception(); Index: libtorrent/scripts/common.m4 =================================================================== --- libtorrent/scripts/common.m4 (revision 1105) +++ libtorrent/scripts/common.m4 (working copy) @@ -184,7 +184,7 @@ AC_DEFUN([TORRENT_CHECK_EXECINFO], [ AC_MSG_CHECKING(for execinfo.h) - AC_RUN_IFELSE( + AC_LINK_IFELSE( [[#include int main() { backtrace((void**)0, 0); backtrace_symbols((char**)0, 0); return 0;} ]], Index: libtorrent/src/torrent/exceptions.cc =================================================================== --- libtorrent/src/torrent/exceptions.cc (revision 1105) +++ libtorrent/src/torrent/exceptions.cc (working copy) @@ -39,6 +39,10 @@ #include #include +#ifdef USE_EXECINFO +#include +#endif + #include "exceptions.h" namespace torrent { @@ -47,9 +51,22 @@ // exceptions. This allows us to create breakpoints at throws. This is // limited to rarely thrown exceptions. -internal_error::internal_error(const char* msg) : m_msg(msg) { +internal_error::internal_error(const char* msg) : + m_msg(msg), + m_stackSize(0) { + +#ifdef USE_EXECINFO + m_stackSize = backtrace(m_stackPtrs, 20); +#endif } -internal_error::internal_error(const std::string& msg) : m_msg(msg) { + +internal_error::internal_error(const std::string& msg) : + m_msg(msg), + m_stackSize(0) { + +#ifdef USE_EXECINFO + m_stackSize = backtrace(m_stackPtrs, 20); +#endif } communication_error::communication_error(const char* msg) : m_msg(msg) {} Index: libtorrent/src/torrent/exceptions.h =================================================================== --- libtorrent/src/torrent/exceptions.h (revision 1105) +++ libtorrent/src/torrent/exceptions.h (working copy) @@ -66,8 +66,15 @@ virtual const char* what() const throw() { return m_msg.c_str(); } + typedef void* stack_t[20]; + + int stack_size() { return m_stackSize; } + stack_t& get_stack() { return m_stackPtrs; } + private: std::string m_msg; + int m_stackSize; + stack_t m_stackPtrs; }; // For some reason we couldn't talk with a protocol/tracker, migth be a Index: libtorrent/configure.ac =================================================================== --- libtorrent/configure.ac (revision 1105) +++ libtorrent/configure.ac (working copy) @@ -81,6 +81,7 @@ CXXFLAGS="$CXXFLAGS $STUFF_CFLAGS"; LIBS="$LIBS $STUFF_LIBS") +TORRENT_CHECK_EXECINFO() TORRENT_CHECK_MADVISE() TORRENT_MINCORE() TORRENT_OTFD()