/src/breakpad/BreakPad.cpp

http://github.com/tomahawk-player/tomahawk · C++ · 179 lines · 104 code · 40 blank · 35 comment · 13 complexity · 4be2badb0d82fa3027e199d62779457c MD5 · raw file

  1. /* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
  2. *
  3. * Copyright 2010-2011, Christian Muehlhaeuser <muesli@tomahawk-player.org>
  4. *
  5. * Tomahawk is free software: you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License as published by
  7. * the Free Software Foundation, either version 3 of the License, or
  8. * (at your option) any later version.
  9. *
  10. * Tomahawk is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU General Public License
  16. * along with Tomahawk. If not, see <http://www.gnu.org/licenses/>.
  17. */
  18. #include "BreakPad.h"
  19. #include "config.h"
  20. #include "utils/Logger.h"
  21. #include <QCoreApplication>
  22. #include <QString>
  23. #include <QFileInfo>
  24. #include <string.h>
  25. #define CRASH_REPORTER_BINARY "tomahawk_crash_reporter"
  26. bool s_active = true;
  27. #ifndef WIN32
  28. #include <unistd.h>
  29. static bool
  30. LaunchUploader( const char* dump_dir, const char* minidump_id, void* that, bool succeeded )
  31. {
  32. // DON'T USE THE HEAP!!!
  33. // So that indeed means, no QStrings, no qDebug(), no QAnything, seriously!
  34. if ( !succeeded )
  35. return false;
  36. const char* crashReporter = static_cast<BreakPad*>(that)->crashReporter();
  37. if ( !s_active || strlen( crashReporter ) == 0 )
  38. return false;
  39. pid_t pid = fork();
  40. if ( pid == -1 ) // fork failed
  41. return false;
  42. if ( pid == 0 )
  43. {
  44. // we are the fork
  45. execl( crashReporter,
  46. crashReporter,
  47. dump_dir,
  48. minidump_id,
  49. minidump_id,
  50. (char*) 0 );
  51. // execl replaces this process, so no more code will be executed
  52. // unless it failed. If it failed, then we should return false.
  53. printf( "Error: Can't launch CrashReporter!\n" );
  54. return false;
  55. }
  56. // we called fork()
  57. return true;
  58. }
  59. BreakPad::BreakPad( const QString& path, bool active )
  60. #ifdef Q_OS_LINUX
  61. : google_breakpad::ExceptionHandler( path.toStdString(), 0, LaunchUploader, this, true )
  62. #else
  63. : google_breakpad::ExceptionHandler( path.toStdString(), 0, LaunchUploader, this, true, 0 )
  64. #endif
  65. {
  66. s_active = active;
  67. QString reporter;
  68. QString localReporter = QString( "%1/%2" ).arg( qApp->applicationDirPath() ).arg( CRASH_REPORTER_BINARY );
  69. QString globalReporter = QString( "%1/%2" ).arg( CMAKE_INSTALL_FULL_LIBEXECDIR ).arg( CRASH_REPORTER_BINARY );
  70. if ( QFileInfo( localReporter ).exists() )
  71. reporter = localReporter;
  72. else if ( QFileInfo( globalReporter ).exists() )
  73. reporter = globalReporter;
  74. else
  75. tLog() << "Could not find \"" CRASH_REPORTER_BINARY "\" in \"" CMAKE_INSTALL_FULL_LIBEXECDIR "\" or application path";
  76. char* creporter;
  77. std::string sreporter = reporter.toStdString();
  78. creporter = new char[ sreporter.size() + 1 ];
  79. strcpy( creporter, sreporter.c_str() );
  80. m_crashReporter = creporter;
  81. }
  82. #else
  83. static bool
  84. LaunchUploader( const wchar_t* dump_dir, const wchar_t* minidump_id, void* that, EXCEPTION_POINTERS *exinfo, MDRawAssertionInfo *assertion, bool succeeded )
  85. {
  86. if ( !succeeded )
  87. return false;
  88. // DON'T USE THE HEAP!!!
  89. // So that indeed means, no QStrings, no qDebug(), no QAnything, seriously!
  90. // broken in mingw, hardcode it for now
  91. // const char* productName = static_cast<BreakPad*>(that)->productName();s
  92. // convert productName to widechars, which sadly means the product name must be Latin1
  93. wchar_t product_name[ 256 ] = L"tomahawk";;
  94. // char* out = (char*)product_name;
  95. // const char* in = productName - 1;
  96. // do {
  97. // *out++ = *++in; //latin1 chars fit in first byte of each wchar
  98. // *out++ = '\0'; //every second byte is NULL
  99. // }
  100. // while (*in);
  101. wchar_t command[MAX_PATH * 3 + 6];
  102. wcscpy( command, CRASH_REPORTER_BINARY L" \"" );
  103. wcscat( command, dump_dir );
  104. wcscat( command, L"\" \"" );
  105. wcscat( command, minidump_id );
  106. wcscat( command, L"\" \"" );
  107. wcscat( command, product_name );
  108. wcscat( command, L"\"" );
  109. STARTUPINFO si;
  110. PROCESS_INFORMATION pi;
  111. ZeroMemory( &si, sizeof( si ) );
  112. si.cb = sizeof(si);
  113. si.dwFlags = STARTF_USESHOWWINDOW;
  114. si.wShowWindow = SW_SHOWNORMAL;
  115. ZeroMemory( &pi, sizeof(pi) );
  116. if ( CreateProcess( NULL, command, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi ) )
  117. {
  118. CloseHandle( pi.hProcess );
  119. CloseHandle( pi.hThread );
  120. TerminateProcess( GetCurrentProcess(), 1 );
  121. }
  122. return false;
  123. }
  124. BreakPad::BreakPad( const QString& path, bool active )
  125. : google_breakpad::ExceptionHandler( path.toStdWString(), 0, LaunchUploader, this, true )
  126. {
  127. s_active = active;
  128. }
  129. #endif // WIN32
  130. void
  131. BreakPad::setActive( bool enabled )
  132. {
  133. s_active = enabled;
  134. }
  135. bool
  136. BreakPad::isActive()
  137. {
  138. return s_active;
  139. }