/src/breakpad/BreakPad.cpp
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 19#include "BreakPad.h" 20 21#include "config.h" 22#include "utils/Logger.h" 23 24#include <QCoreApplication> 25#include <QString> 26#include <QFileInfo> 27#include <string.h> 28 29#define CRASH_REPORTER_BINARY "tomahawk_crash_reporter" 30 31bool s_active = true; 32 33#ifndef WIN32 34#include <unistd.h> 35 36 37static bool 38LaunchUploader( const char* dump_dir, const char* minidump_id, void* that, bool succeeded ) 39{ 40 // DON'T USE THE HEAP!!! 41 // So that indeed means, no QStrings, no qDebug(), no QAnything, seriously! 42 43 if ( !succeeded ) 44 return false; 45 46 const char* crashReporter = static_cast<BreakPad*>(that)->crashReporter(); 47 if ( !s_active || strlen( crashReporter ) == 0 ) 48 return false; 49 50 pid_t pid = fork(); 51 if ( pid == -1 ) // fork failed 52 return false; 53 if ( pid == 0 ) 54 { 55 // we are the fork 56 execl( crashReporter, 57 crashReporter, 58 dump_dir, 59 minidump_id, 60 minidump_id, 61 (char*) 0 ); 62 63 // execl replaces this process, so no more code will be executed 64 // unless it failed. If it failed, then we should return false. 65 printf( "Error: Can't launch CrashReporter!\n" ); 66 return false; 67 } 68 69 // we called fork() 70 return true; 71} 72 73 74BreakPad::BreakPad( const QString& path, bool active ) 75#ifdef Q_OS_LINUX 76 : google_breakpad::ExceptionHandler( path.toStdString(), 0, LaunchUploader, this, true ) 77#else 78 : google_breakpad::ExceptionHandler( path.toStdString(), 0, LaunchUploader, this, true, 0 ) 79#endif 80{ 81 s_active = active; 82 83 QString reporter; 84 QString localReporter = QString( "%1/%2" ).arg( qApp->applicationDirPath() ).arg( CRASH_REPORTER_BINARY ); 85 QString globalReporter = QString( "%1/%2" ).arg( CMAKE_INSTALL_FULL_LIBEXECDIR ).arg( CRASH_REPORTER_BINARY ); 86 87 if ( QFileInfo( localReporter ).exists() ) 88 reporter = localReporter; 89 else if ( QFileInfo( globalReporter ).exists() ) 90 reporter = globalReporter; 91 else 92 tLog() << "Could not find \"" CRASH_REPORTER_BINARY "\" in \"" CMAKE_INSTALL_FULL_LIBEXECDIR "\" or application path"; 93 94 char* creporter; 95 std::string sreporter = reporter.toStdString(); 96 creporter = new char[ sreporter.size() + 1 ]; 97 strcpy( creporter, sreporter.c_str() ); 98 99 m_crashReporter = creporter; 100} 101 102 103#else 104 105 106static bool 107LaunchUploader( const wchar_t* dump_dir, const wchar_t* minidump_id, void* that, EXCEPTION_POINTERS *exinfo, MDRawAssertionInfo *assertion, bool succeeded ) 108{ 109 if ( !succeeded ) 110 return false; 111 112 // DON'T USE THE HEAP!!! 113 // So that indeed means, no QStrings, no qDebug(), no QAnything, seriously! 114 115// broken in mingw, hardcode it for now 116 117 // const char* productName = static_cast<BreakPad*>(that)->productName();s 118 // convert productName to widechars, which sadly means the product name must be Latin1 119 120 wchar_t product_name[ 256 ] = L"tomahawk";; 121 122// char* out = (char*)product_name; 123// const char* in = productName - 1; 124// do { 125// *out++ = *++in; //latin1 chars fit in first byte of each wchar 126// *out++ = '\0'; //every second byte is NULL 127// } 128// while (*in); 129 130 wchar_t command[MAX_PATH * 3 + 6]; 131 wcscpy( command, CRASH_REPORTER_BINARY L" \"" ); 132 wcscat( command, dump_dir ); 133 wcscat( command, L"\" \"" ); 134 wcscat( command, minidump_id ); 135 wcscat( command, L"\" \"" ); 136 wcscat( command, product_name ); 137 wcscat( command, L"\"" ); 138 139 STARTUPINFO si; 140 PROCESS_INFORMATION pi; 141 142 ZeroMemory( &si, sizeof( si ) ); 143 si.cb = sizeof(si); 144 si.dwFlags = STARTF_USESHOWWINDOW; 145 si.wShowWindow = SW_SHOWNORMAL; 146 ZeroMemory( &pi, sizeof(pi) ); 147 148 if ( CreateProcess( NULL, command, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi ) ) 149 { 150 CloseHandle( pi.hProcess ); 151 CloseHandle( pi.hThread ); 152 TerminateProcess( GetCurrentProcess(), 1 ); 153 } 154 155 return false; 156} 157 158 159BreakPad::BreakPad( const QString& path, bool active ) 160 : google_breakpad::ExceptionHandler( path.toStdWString(), 0, LaunchUploader, this, true ) 161{ 162 s_active = active; 163} 164 165#endif // WIN32 166 167 168void 169BreakPad::setActive( bool enabled ) 170{ 171 s_active = enabled; 172} 173 174 175bool 176BreakPad::isActive() 177{ 178 return s_active; 179}