Automatic back traces on windows.
[quassel.git] / src / common / quassel.cpp
index d06aa28..29b6e55 100644 (file)
 #include "types.h"
 #include "syncableobject.h"
 
-#if defined(HAVE_EXECINFO) && !defined(Q_OS_MAC)
-#  define BUILD_CRASHHANDLER
-#  include <execinfo.h>
-#  include <dlfcn.h>
-#  include <cxxabi.h>
-#endif
-
 Quassel::BuildInfo Quassel::_buildInfo;
 CliParser *Quassel::_cliParser = 0;
 Quassel::RunMode Quassel::_runMode;
@@ -55,11 +48,15 @@ Quassel::Quassel() {
   signal(SIGTERM, handleSignal);
   signal(SIGINT, handleSignal);
 
-#ifdef BUILD_CRASHHANDLER
+  // we have crashhandler for win32 and unix (based on execinfo).
+  // on mac os we use it's integrated backtrace generator
+#if defined(Q_OS_WIN32) || (defined(HAVE_EXECINFO) && !defined(Q_OS_MAC))
   signal(SIGABRT, handleSignal);
-  signal(SIGBUS, handleSignal);
   signal(SIGSEGV, handleSignal);
-#endif // #if defined(HAVE_EXECINFO) && !defined(Q_OS_MAC)
+#  ifndef Q_OS_WIN32
+  signal(SIGBUS, handleSignal);
+#  endif
+#endif
 
   _cliParser = new CliParser();
 
@@ -207,109 +204,47 @@ void Quassel::setupBuildInfo(const QString &generated) {
 //! Signal handler for graceful shutdown.
 void Quassel::handleSignal(int sig) {
   switch(sig) {
-    case SIGTERM:
-    case SIGINT:
-      qWarning("%s", qPrintable(QString("Caught signal %1 - exiting.").arg(sig)));
-      QCoreApplication::quit();
-      break;
-
-#ifdef BUILD_CRASHHANDLER
-    case SIGABRT:
-    case SIGBUS:
-    case SIGSEGV:
-      handleCrash();
+  case SIGTERM:
+  case SIGINT:
+    qWarning("%s", qPrintable(QString("Caught signal %1 - exiting.").arg(sig)));
+    QCoreApplication::quit();
+    break;
+  case SIGABRT:
+  case SIGSEGV:
+#ifndef Q_OS_WIN32
+  case SIGBUS:
 #endif
-      break;
-    default:
-      break;
+    logBacktrace(coreDumpFileName());
+    break;
+  default:
+    break;
   }
 }
 
 void Quassel::logFatalMessage(const char *msg) {
-#ifndef Q_OS_MAC
+#ifdef Q_OS_MAC
+  Q_UNUSED(msg)
+#else
   QFile dumpFile(coreDumpFileName());
-  dumpFile.open(QIODevice::WriteOnly);
+  dumpFile.open(QIODevice::Append);
   QTextStream dumpStream(&dumpFile);
-#else
-  QTextStream dumpStream(stderr);
-#endif
   
   dumpStream << "Fatal: " << msg << '\n';
   dumpStream.flush();
-
-  qInstallMsgHandler(0);
-  abort();
-}
-
-void Quassel::handleCrash() {
-#ifdef BUILD_CRASHHANDLER
-  void* callstack[128];
-  int i, frames = backtrace(callstack, 128);
-
-  QFile dumpFile(coreDumpFileName());
-  dumpFile.open(QIODevice::Append);
-  QTextStream dumpStream(&dumpFile);
-
-  dumpStream << "Quassel IRC: " << _buildInfo.baseVersion << ' ' << _buildInfo.commitHash << '\n';
-    
-  for (i = 0; i < frames; ++i) {
-    Dl_info info;
-    dladdr (callstack[i], &info);
-    // as a reference:
-    //     typedef struct
-    //     {
-      //       __const char *dli_fname;   /* File name of defining object.  */
-    //       void *dli_fbase;           /* Load address of that object.  */
-    //       __const char *dli_sname;   /* Name of nearest symbol.  */
-    //       void *dli_saddr;           /* Exact value of nearest symbol.  */
-    //     } Dl_info;
-
-    #if __LP64__
-    int addrSize = 16;
-    #else
-    int addrSize = 8;
-    #endif
-
-    QString funcName;
-    if(info.dli_sname) {
-      char *func = abi::__cxa_demangle(info.dli_sname, 0, 0, 0);
-      if(func) {
-        funcName = QString(func);
-        free(func);
-      } else {
-        funcName = QString(info.dli_sname);
-      }
-    } else {
-      funcName = QString("0x%1").arg((long)info.dli_saddr, addrSize, QLatin1Char('0'));
-    }
-
-    // prettificating the filename
-    QString fileName("???");
-    if(info.dli_fname) {
-      fileName = QString(info.dli_fname);
-      int slashPos = fileName.lastIndexOf('/');
-      if(slashPos != -1)
-        fileName = fileName.mid(slashPos + 1);
-      if(fileName.count() < 20)
-        fileName += QString(20 - fileName.count(), ' ');
-    }
-
-    QString debugLine = QString("#%1 %2 0x%3 %4").arg(i, 3, 10)
-    .arg(fileName)
-    .arg((long)(callstack[i]), addrSize, 16, QLatin1Char('0'))
-    .arg(funcName);
-
-    dumpStream << debugLine << "\n";
-    qDebug() << qPrintable(debugLine);
-  }
   dumpFile.close();
-  exit(27);
-#endif /* BUILD_CRASHHANDLER */
+#endif
 }
 
 const QString &Quassel::coreDumpFileName() {
-  if(_coreDumpFileName.isEmpty())
+  if(_coreDumpFileName.isEmpty()) {
     _coreDumpFileName = QString("Quassel-Crash-%1.log").arg(QDateTime::currentDateTime().toString("yyyyMMdd-hhmm"));
-
+    QFile dumpFile(_coreDumpFileName);
+    dumpFile.open(QIODevice::Append);
+    QTextStream dumpStream(&dumpFile);
+    dumpStream << "Quassel IRC: " << _buildInfo.baseVersion << ' ' << _buildInfo.commitHash << '\n';
+    qDebug() << "Quassel IRC: " << _buildInfo.baseVersion << ' ' << _buildInfo.commitHash;
+    dumpStream.flush();
+    dumpFile.close();
+  }
   return _coreDumpFileName;
 }