QBreakpadHandler.cpp 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181
  1. /*
  2. * Copyright (C) 2009 Aleksey Palazhchenko
  3. * Copyright (C) 2014 Sergey Shambir
  4. * Copyright (C) 2016 Alexander Makarov
  5. *
  6. * This file is a part of Breakpad-qt library.
  7. *
  8. * This library is free software; you can redistribute it and/or
  9. * modify it under the terms of the GNU Lesser General Public
  10. * License as published by the Free Software Foundation; either
  11. * version 2.1 of the License, or (at your option) any later version.
  12. *
  13. * This library is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  16. * Lesser General Public License for more details.
  17. *
  18. */
  19. #include <QDir>
  20. #include <QProcess>
  21. #include <QCoreApplication>
  22. #include <QMessageBox>
  23. #include "QBreakpadHandler.h"
  24. #include "QBreakpadHttpUploader.h"
  25. #define QBREAKPAD_VERSION 0x000400
  26. #if defined(Q_OS_MAC)
  27. #include "client/mac/handler/exception_handler.h"
  28. #elif defined(Q_OS_LINUX)
  29. #include "client/linux/handler/exception_handler.h"
  30. #elif defined(Q_OS_WIN32)
  31. #include "client/windows/handler/exception_handler.h"
  32. #endif
  33. #if defined(Q_OS_WIN32)
  34. bool DumpCallback(const wchar_t* dump_dir,
  35. const wchar_t* minidump_id,
  36. void* context,
  37. EXCEPTION_POINTERS* exinfo,
  38. MDRawAssertionInfo* assertion,
  39. bool succeeded)
  40. #elif defined(Q_OS_MAC)
  41. bool DumpCallback(const char *dump_dir,
  42. const char *minidump_id,
  43. void *context, bool succeeded)
  44. #else
  45. bool DumpCallback(const google_breakpad::MinidumpDescriptor& descriptor,
  46. void* context,
  47. bool succeeded)
  48. #endif
  49. {
  50. #ifdef Q_OS_LINUX
  51. Q_UNUSED(descriptor);
  52. #endif
  53. Q_UNUSED(context);
  54. #if defined(Q_OS_WIN32)
  55. Q_UNUSED(assertion);
  56. Q_UNUSED(exinfo);
  57. #endif
  58. /*
  59. NO STACK USE, NO HEAP USE THERE !!!
  60. Creating QString's, using qDebug, etc. - everything is crash-unfriendly.
  61. */
  62. #if defined(Q_OS_WIN32)
  63. QString path = QString::fromWCharArray(dump_dir) + QLatin1String("/") + QString::fromWCharArray(minidump_id);
  64. qDebug("%s, dump path: %s\n", succeeded ? "Succeed to write minidump" : "Failed to write minidump", qPrintable(path));
  65. #elif defined(Q_OS_MAC)
  66. QString path = QString::fromUtf8(dump_dir) + QLatin1String("/") + QString::fromUtf8(minidump_id);
  67. qDebug("%s, dump path: %s\n", succeeded ? "Succeed to write minidump" : "Failed to write minidump", qPrintable(path));
  68. #else
  69. qDebug("%s, dump path: %s\n", succeeded ? "Succeed to write minidump" : "Failed to write minidump", descriptor.path());
  70. #endif
  71. return succeeded;
  72. }
  73. class QBreakpadHandlerPrivate
  74. {
  75. public:
  76. google_breakpad::ExceptionHandler* pExptHandler;
  77. QString dumpPath;
  78. QUrl uploadUrl;
  79. };
  80. //------------------------------------------------------------------------------
  81. QString QBreakpadHandler::version()
  82. {
  83. return QString("%1.%2.%3").arg(
  84. QString::number((QBREAKPAD_VERSION >> 16) & 0xff),
  85. QString::number((QBREAKPAD_VERSION >> 8) & 0xff),
  86. QString::number(QBREAKPAD_VERSION & 0xff));
  87. }
  88. QBreakpadHandler::QBreakpadHandler() :
  89. d(new QBreakpadHandlerPrivate())
  90. {
  91. }
  92. QBreakpadHandler::~QBreakpadHandler()
  93. {
  94. delete d;
  95. }
  96. void QBreakpadHandler::setDumpPath(const QString& path)
  97. {
  98. QString absPath = path;
  99. if(!QDir::isAbsolutePath(absPath)) {
  100. absPath = QDir::cleanPath(qApp->applicationDirPath() + "/" + path);
  101. }
  102. Q_ASSERT(QDir::isAbsolutePath(absPath));
  103. QDir().mkpath(absPath);
  104. if (!QDir().exists(absPath)) {
  105. qDebug("Failed to set dump path which not exists: %s", qPrintable(absPath));
  106. return;
  107. }
  108. d->dumpPath = absPath;
  109. // NOTE: ExceptionHandler initialization
  110. #if defined(Q_OS_WIN32)
  111. d->pExptHandler = new google_breakpad::ExceptionHandler(absPath.toStdWString(), /*FilterCallback*/ 0,
  112. DumpCallback, /*context*/ 0,
  113. google_breakpad::ExceptionHandler::HANDLER_ALL);
  114. #elif defined(Q_OS_MAC)
  115. d->pExptHandler = new google_breakpad::ExceptionHandler(absPath.toStdString(),
  116. /*FilterCallback*/ 0,
  117. DumpCallback, /*context*/ 0, true, NULL);
  118. #else
  119. d->pExptHandler = new google_breakpad::ExceptionHandler(google_breakpad::MinidumpDescriptor(absPath.toStdString()),
  120. /*FilterCallback*/ 0,
  121. DumpCallback,
  122. /*context*/ 0,
  123. true,
  124. -1);
  125. #endif
  126. }
  127. QString QBreakpadHandler::uploadUrl() const
  128. {
  129. return d->uploadUrl.toString();
  130. }
  131. QStringList QBreakpadHandler::dumpFileList() const
  132. {
  133. if(!d->dumpPath.isNull() && !d->dumpPath.isEmpty()) {
  134. QDir dumpDir(d->dumpPath);
  135. dumpDir.setNameFilters(QStringList()<<"*.dmp");
  136. return dumpDir.entryList();
  137. }
  138. return QStringList();
  139. }
  140. void QBreakpadHandler::setUploadUrl(const QUrl &url)
  141. {
  142. if(!url.isValid() || url.isEmpty())
  143. return;
  144. d->uploadUrl = url;
  145. }
  146. void QBreakpadHandler::sendDumps()
  147. {
  148. if(!d->dumpPath.isNull() && !d->dumpPath.isEmpty()) {
  149. QDir dumpDir(d->dumpPath);
  150. dumpDir.setNameFilters(QStringList()<<"*.dmp");
  151. QStringList dumpFiles = dumpDir.entryList();
  152. foreach(QString itDmpFileName, dumpFiles) {
  153. qDebug() << "Sending " << QString(itDmpFileName);
  154. QBreakpadHttpUploader *sender = new QBreakpadHttpUploader(d->uploadUrl);
  155. sender->uploadDump(d->dumpPath + "/" + itDmpFileName);
  156. }
  157. }
  158. }