PageRenderTime 103ms CodeModel.GetById 40ms app.highlight 13ms RepoModel.GetById 47ms app.codeStats 0ms

/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
 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}