Commit 4beaae0f authored by Marco Bubke's avatar Marco Bubke Committed by Orgad Shaneh

Introduce Breakpad crash handler

Google Breakpad (https://chromium.googlesource.com/breakpad/breakpad) is a
widely used crash handler framework, e.g. by Mozilla and Chromium. It is
providing a platform neutral solution to generate mini dumps, collect
debug information and generate stack traces from those.

Done-with: Orgad Shaneh <orgad.shaneh@audiocodes.com>
Change-Id: I09382e7db0dc9e29b228e7b554fda7b6f5684349
Reviewed-by: Orgad Shaneh's avatarOrgad Shaneh <orgads@gmail.com>
Reviewed-by: Tim Jenssen's avatarTim Jenssen <tim.jenssen@qt.io>
parent 131a796f
......@@ -51,6 +51,7 @@ wrapper.sh
/src/app/Info.plist
/src/plugins/**/*.json
/src/plugins/coreplugin/ide_version.h
/src/libs/qt-breakpad/bin
app_version.h
phony.c
......
......@@ -13,11 +13,6 @@ include (../interfaces/interfaces.pri)
include (../types/types.pri)
include (../qmlprivategate/qmlprivategate.pri)
QT_BREAKPAD_ROOT_PATH = $$(QT_BREAKPAD_ROOT_PATH)
!isEmpty(QT_BREAKPAD_ROOT_PATH) {
include($$QT_BREAKPAD_ROOT_PATH/qtbreakpad.pri)
}
SOURCES += $$PWD/qml2puppetmain.cpp
RESOURCES += $$PWD/../qmlpuppet.qrc
......
......@@ -111,7 +111,8 @@ int internalMain(QGuiApplication *application)
#ifdef ENABLE_QT_BREAKPAD
QtSystemExceptionHandler systemExceptionHandler;
const QString libexecPath = QCoreApplication::applicationDirPath() + '/' + RELATIVE_LIBEXEC_PATH;
QtSystemExceptionHandler systemExceptionHandler(libexecPath);
#endif
new QmlDesigner::Qt5NodeInstanceClientProxy(application);
......
......@@ -12,13 +12,10 @@ HEADERS += ../tools/qtcreatorcrashhandler/crashhandlersetup.h
SOURCES += main.cpp ../tools/qtcreatorcrashhandler/crashhandlersetup.cpp
include(../rpath.pri)
include(../libs/qt-breakpad/qtbreakpad.pri)
LIBS *= -l$$qtLibraryName(ExtensionSystem) -l$$qtLibraryName(Aggregation) -l$$qtLibraryName(Utils)
QT_BREAKPAD_ROOT_PATH = $$(QT_BREAKPAD_ROOT_PATH)
!isEmpty(QT_BREAKPAD_ROOT_PATH) {
include($$QT_BREAKPAD_ROOT_PATH/qtbreakpad.pri)
}
win32 {
# We need the version in two separate formats for the .rc file
# RC_VERSION=4,3,82,0 (quadruple)
......
......@@ -329,13 +329,13 @@ int main(int argc, char **argv)
const int threadCount = QThreadPool::globalInstance()->maxThreadCount();
QThreadPool::globalInstance()->setMaxThreadCount(qMax(4, 2 * threadCount));
// Display a backtrace once a serious signal is delivered (Linux only).
const QString libexecPath = QCoreApplication::applicationDirPath()
+ '/' + RELATIVE_LIBEXEC_PATH;
CrashHandlerSetup setupCrashHandler(appNameC, CrashHandlerSetup::EnableRestart, libexecPath);
#ifdef ENABLE_QT_BREAKPAD
QtSystemExceptionHandler systemExceptionHandler;
QtSystemExceptionHandler systemExceptionHandler(libexecPath);
#else
// Display a backtrace once a serious signal is delivered (Linux only).
CrashHandlerSetup setupCrashHandler(appNameC, CrashHandlerSetup::EnableRestart, libexecPath);
#endif
app.setAttribute(Qt::AA_UseHighDpiPixmaps);
......
# Copyright (c) 2010 Chris AtLee
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
"""poster module
Support for streaming HTTP uploads, and multipart/form-data encoding
```poster.version``` is a 3-tuple of integers representing the version number.
New releases of poster will always have a version number that compares greater
than an older version of poster.
New in version 0.6."""
import poster.streaminghttp
import poster.encode
version = (0, 8, 0) # Thanks JP!
This diff is collapsed.
# Copyright (c) 2010 Chris AtLee
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
"""Streaming HTTP uploads module.
This module extends the standard httplib and urllib2 objects so that
iterable objects can be used in the body of HTTP requests.
In most cases all one should have to do is call :func:`register_openers()`
to register the new streaming http handlers which will take priority over
the default handlers, and then you can use iterable objects in the body
of HTTP requests.
**N.B.** You must specify a Content-Length header if using an iterable object
since there is no way to determine in advance the total size that will be
yielded, and there is no way to reset an interator.
Example usage:
>>> from StringIO import StringIO
>>> import urllib2, poster.streaminghttp
>>> opener = poster.streaminghttp.register_openers()
>>> s = "Test file data"
>>> f = StringIO(s)
>>> req = urllib2.Request("http://localhost:5000", f,
... {'Content-Length': str(len(s))})
"""
import httplib, urllib2, socket
from httplib import NotConnected
__all__ = ['StreamingHTTPConnection', 'StreamingHTTPRedirectHandler',
'StreamingHTTPHandler', 'register_openers']
if hasattr(httplib, 'HTTPS'):
__all__.extend(['StreamingHTTPSHandler', 'StreamingHTTPSConnection'])
class _StreamingHTTPMixin:
"""Mixin class for HTTP and HTTPS connections that implements a streaming
send method."""
def send(self, value):
"""Send ``value`` to the server.
``value`` can be a string object, a file-like object that supports
a .read() method, or an iterable object that supports a .next()
method.
"""
# Based on python 2.6's httplib.HTTPConnection.send()
if self.sock is None:
if self.auto_open:
self.connect()
else:
raise NotConnected()
# send the data to the server. if we get a broken pipe, then close
# the socket. we want to reconnect when somebody tries to send again.
#
# NOTE: we DO propagate the error, though, because we cannot simply
# ignore the error... the caller will know if they can retry.
if self.debuglevel > 0:
print "send:", repr(value)
try:
blocksize = 8192
if hasattr(value, 'read') :
if hasattr(value, 'seek'):
value.seek(0)
if self.debuglevel > 0:
print "sendIng a read()able"
data = value.read(blocksize)
while data:
self.sock.sendall(data)
data = value.read(blocksize)
elif hasattr(value, 'next'):
if hasattr(value, 'reset'):
value.reset()
if self.debuglevel > 0:
print "sendIng an iterable"
for data in value:
self.sock.sendall(data)
else:
self.sock.sendall(value)
except socket.error, v:
if v[0] == 32: # Broken pipe
self.close()
raise
class StreamingHTTPConnection(_StreamingHTTPMixin, httplib.HTTPConnection):
"""Subclass of `httplib.HTTPConnection` that overrides the `send()` method
to support iterable body objects"""
class StreamingHTTPRedirectHandler(urllib2.HTTPRedirectHandler):
"""Subclass of `urllib2.HTTPRedirectHandler` that overrides the
`redirect_request` method to properly handle redirected POST requests
This class is required because python 2.5's HTTPRedirectHandler does
not remove the Content-Type or Content-Length headers when requesting
the new resource, but the body of the original request is not preserved.
"""
handler_order = urllib2.HTTPRedirectHandler.handler_order - 1
# From python2.6 urllib2's HTTPRedirectHandler
def redirect_request(self, req, fp, code, msg, headers, newurl):
"""Return a Request or None in response to a redirect.
This is called by the http_error_30x methods when a
redirection response is received. If a redirection should
take place, return a new Request to allow http_error_30x to
perform the redirect. Otherwise, raise HTTPError if no-one
else should try to handle this url. Return None if you can't
but another Handler might.
"""
m = req.get_method()
if (code in (301, 302, 303, 307) and m in ("GET", "HEAD")
or code in (301, 302, 303) and m == "POST"):
# Strictly (according to RFC 2616), 301 or 302 in response
# to a POST MUST NOT cause a redirection without confirmation
# from the user (of urllib2, in this case). In practice,
# essentially all clients do redirect in this case, so we
# do the same.
# be conciliant with URIs containing a space
newurl = newurl.replace(' ', '%20')
newheaders = dict((k, v) for k, v in req.headers.items()
if k.lower() not in (
"content-length", "content-type")
)
return urllib2.Request(newurl,
headers=newheaders,
origin_req_host=req.get_origin_req_host(),
unverifiable=True)
else:
raise urllib2.HTTPError(req.get_full_url(), code, msg, headers, fp)
class StreamingHTTPHandler(urllib2.HTTPHandler):
"""Subclass of `urllib2.HTTPHandler` that uses
StreamingHTTPConnection as its http connection class."""
handler_order = urllib2.HTTPHandler.handler_order - 1
def http_open(self, req):
"""Open a StreamingHTTPConnection for the given request"""
return self.do_open(StreamingHTTPConnection, req)
def http_request(self, req):
"""Handle a HTTP request. Make sure that Content-Length is specified
if we're using an interable value"""
# Make sure that if we're using an iterable object as the request
# body, that we've also specified Content-Length
if req.has_data():
data = req.get_data()
if hasattr(data, 'read') or hasattr(data, 'next'):
if not req.has_header('Content-length'):
raise ValueError(
"No Content-Length specified for iterable body")
return urllib2.HTTPHandler.do_request_(self, req)
if hasattr(httplib, 'HTTPS'):
class StreamingHTTPSConnection(_StreamingHTTPMixin,
httplib.HTTPSConnection):
"""Subclass of `httplib.HTTSConnection` that overrides the `send()`
method to support iterable body objects"""
class StreamingHTTPSHandler(urllib2.HTTPSHandler):
"""Subclass of `urllib2.HTTPSHandler` that uses
StreamingHTTPSConnection as its http connection class."""
handler_order = urllib2.HTTPSHandler.handler_order - 1
def https_open(self, req):
return self.do_open(StreamingHTTPSConnection, req)
def https_request(self, req):
# Make sure that if we're using an iterable object as the request
# body, that we've also specified Content-Length
if req.has_data():
data = req.get_data()
if hasattr(data, 'read') or hasattr(data, 'next'):
if not req.has_header('Content-length'):
raise ValueError(
"No Content-Length specified for iterable body")
return urllib2.HTTPSHandler.do_request_(self, req)
def register_openers():
"""Register the streaming http handlers in the global urllib2 default
opener object.
Returns the created OpenerDirector object."""
handlers = [StreamingHTTPHandler, StreamingHTTPRedirectHandler]
if hasattr(httplib, "HTTPS"):
handlers.append(StreamingHTTPSHandler)
opener = urllib2.build_opener(*handlers)
urllib2.install_opener(opener)
return opener
isEmpty(BREAKPAD_SOURCE_DIR): return()
HEADERS += $$PWD/qtbreakpad/qtsystemexceptionhandler.h
SOURCES += $$PWD/qtbreakpad/qtsystemexceptionhandler.cpp
DEFINES += ENABLE_QT_BREAKPAD
win32:BREAKPAD_SOURCE_DIR ~= s,\\,/,
INCLUDEPATH += \
$$BREAKPAD_SOURCE_DIR/src \
$$PWD/qtbreakpad
SOURCES += \
$$BREAKPAD_SOURCE_DIR/src/common/string_conversion.cc \
$$BREAKPAD_SOURCE_DIR/src/common/convert_UTF.c \
$$BREAKPAD_SOURCE_DIR/src/common/md5.cc
linux:SOURCES += \
$$BREAKPAD_SOURCE_DIR/src/client/minidump_file_writer.cc \
$$BREAKPAD_SOURCE_DIR/src/client/linux/log/log.cc \
$$BREAKPAD_SOURCE_DIR/src/client/linux/handler/exception_handler.cc \
$$BREAKPAD_SOURCE_DIR/src/client/linux/handler/minidump_descriptor.cc \
$$BREAKPAD_SOURCE_DIR/src/common/linux/guid_creator.cc \
$$BREAKPAD_SOURCE_DIR/src/client/linux/dump_writer_common/thread_info.cc \
$$BREAKPAD_SOURCE_DIR/src/client/linux/dump_writer_common/ucontext_reader.cc \
$$BREAKPAD_SOURCE_DIR/src/client/linux/minidump_writer/linux_dumper.cc \
$$BREAKPAD_SOURCE_DIR/src/client/linux/minidump_writer/minidump_writer.cc \
$$BREAKPAD_SOURCE_DIR/src/client/linux/minidump_writer/linux_ptrace_dumper.cc \
$$BREAKPAD_SOURCE_DIR/src/client/linux/microdump_writer/microdump_writer.cc \
$$BREAKPAD_SOURCE_DIR/src/common/linux/file_id.cc \
$$BREAKPAD_SOURCE_DIR/src/common/linux/elfutils.cc \
$$BREAKPAD_SOURCE_DIR/src/common/linux/linux_libc_support.cc \
$$BREAKPAD_SOURCE_DIR/src/common/linux/memory_mapped_file.cc \
$$BREAKPAD_SOURCE_DIR/src/common/linux/safe_readlink.cc \
$$BREAKPAD_SOURCE_DIR/src/client/linux/crash_generation/crash_generation_client.cc
win32:SOURCES += \
$$BREAKPAD_SOURCE_DIR/src/common/windows/guid_string.cc \
$$BREAKPAD_SOURCE_DIR/src/client/windows/handler/exception_handler.cc \
$$BREAKPAD_SOURCE_DIR/src/client/windows/crash_generation/minidump_generator.cc \
$$BREAKPAD_SOURCE_DIR/src/client/windows/crash_generation/client_info.cc \
$$BREAKPAD_SOURCE_DIR/src/client/windows/crash_generation/crash_generation_client.cc
macos {
SOURCES += \
$$BREAKPAD_SOURCE_DIR/src/client/minidump_file_writer.cc \
$$BREAKPAD_SOURCE_DIR/src/client/mac/crash_generation/crash_generation_client.cc \
$$BREAKPAD_SOURCE_DIR/src/client/mac/handler/exception_handler.cc \
$$BREAKPAD_SOURCE_DIR/src/client/mac/handler/minidump_generator.cc \
$$BREAKPAD_SOURCE_DIR/src/client/mac/handler/breakpad_nlist_64.cc \
$$BREAKPAD_SOURCE_DIR/src/client/mac/handler/dynamic_images.cc \
$$BREAKPAD_SOURCE_DIR/src/client/mac/handler/protected_memory_allocator.cc \
$$BREAKPAD_SOURCE_DIR/src/common/mac/bootstrap_compat.cc \
$$BREAKPAD_SOURCE_DIR/src/common/mac/file_id.cc \
$$BREAKPAD_SOURCE_DIR/src/common/mac/macho_id.cc \
$$BREAKPAD_SOURCE_DIR/src/common/mac/macho_reader.cc \
$$BREAKPAD_SOURCE_DIR/src/common/mac/macho_utilities.cc \
$$BREAKPAD_SOURCE_DIR/src/common/mac/macho_walker.cc \
$$BREAKPAD_SOURCE_DIR/src/common/mac/string_utilities.cc
OBJECTIVE_SOURCES += \
$$BREAKPAD_SOURCE_DIR/src/common/mac/MachIPC.mm
LIBS += -framework Foundation
}
/****************************************************************************
**
** Copyright (C) 2017 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
#include "qtsystemexceptionhandler.h"
#include <utils/fileutils.h>
#include <utils/hostosinfo.h>
#include <QCoreApplication>
#include <QDebug>
#include <QDir>
#include <QProcess>
#if defined(Q_OS_LINUX)
# include "client/linux/handler/exception_handler.h"
#elif defined(Q_OS_WIN)
# include "client/windows/handler/exception_handler.h"
#elif defined(Q_OS_MACOS)
# include "client/mac/handler/exception_handler.h"
#endif
#if defined(Q_OS_LINUX)
static bool exceptionHandlerCallback(const google_breakpad::MinidumpDescriptor& descriptor,
void* /*context*/,
bool succeeded)
{
if (!succeeded)
return succeeded;
const QStringList argumentList = {
QString::fromLocal8Bit(descriptor.path()),
QString::number(QtSystemExceptionHandler::startTime().toTime_t()),
QCoreApplication::applicationName(),
QCoreApplication::applicationVersion(),
QtSystemExceptionHandler::plugins(),
QtSystemExceptionHandler::buildVersion(),
QCoreApplication::applicationFilePath()
};
return !QProcess::execute(QtSystemExceptionHandler::crashHandlerPath(), argumentList);
}
#elif defined(Q_OS_MACOS)
static bool exceptionHandlerCallback(const char *dump_dir,
const char *minidump_id,
void *context,
bool succeeded)
{
Q_UNUSED(context);
if (!succeeded)
return succeeded;
const QString path = QString::fromLocal8Bit(dump_dir) + '/'
+ QString::fromLocal8Bit(minidump_id) + ".dmp";
const QStringList argumentList = {
path,
QString::number(QtSystemExceptionHandler::startTime().toTime_t()),
QCoreApplication::applicationName(),
QCoreApplication::applicationVersion(),
QtSystemExceptionHandler::plugins(),
QtSystemExceptionHandler::buildVersion(),
QCoreApplication::applicationFilePath()
};
return !QProcess::execute(QtSystemExceptionHandler::crashHandlerPath(), argumentList);
}
#elif defined(Q_OS_WIN)
static bool exceptionHandlerCallback(const wchar_t* dump_path,
const wchar_t* minidump_id,
void* context,
EXCEPTION_POINTERS* exinfo,
MDRawAssertionInfo* assertion,
bool succeeded)
{
Q_UNUSED(assertion);
Q_UNUSED(exinfo);
Q_UNUSED(context);
if (!succeeded)
return succeeded;
const QString path = QString::fromWCharArray(dump_path, int(wcslen(dump_path))) + '/'
+ QString::fromWCharArray(minidump_id, int(wcslen(minidump_id))) + ".dmp";
const QStringList argumentList = {
path,
QString::number(QtSystemExceptionHandler::startTime().toTime_t()),
QCoreApplication::applicationName(),
QCoreApplication::applicationVersion(),
QtSystemExceptionHandler::plugins(),
QtSystemExceptionHandler::buildVersion(),
QCoreApplication::applicationFilePath()
};
return !QProcess::execute(QtSystemExceptionHandler::crashHandlerPath(), argumentList);
}
#endif
static QDateTime s_startTime;
static QString s_plugins;
static QString s_buildVersion;
static QString s_crashHandlerPath;
#if defined(Q_OS_LINUX)
QtSystemExceptionHandler::QtSystemExceptionHandler(const QString &libexecPath)
: exceptionHandler(new google_breakpad::ExceptionHandler(
google_breakpad::MinidumpDescriptor(QDir::tempPath().toStdString()),
NULL,
exceptionHandlerCallback,
NULL,
true,
-1))
{
init(libexecPath);
}
#elif defined(Q_OS_MACOS)
QtSystemExceptionHandler::QtSystemExceptionHandler(const QString &libexecPath)
: exceptionHandler(new google_breakpad::ExceptionHandler(
QDir::tempPath().toStdString(),
NULL,
exceptionHandlerCallback,
NULL,
true,
NULL))
{
init(libexecPath);
}
#elif defined(Q_OS_WIN)
QtSystemExceptionHandler::QtSystemExceptionHandler(const QString &libexecPath)
: exceptionHandler(new google_breakpad::ExceptionHandler(
QDir::tempPath().toStdWString(),
NULL,
exceptionHandlerCallback,
NULL,
google_breakpad::ExceptionHandler::HANDLER_ALL))
{
init(libexecPath);
}
#else
QtSystemExceptionHandler::QtSystemExceptionHandler(const QString & /*libexecPath*/)
: exceptionHandler(0)
{
}
#endif
void QtSystemExceptionHandler::init(const QString &libexecPath)
{
s_startTime = QDateTime::currentDateTime();
s_crashHandlerPath = libexecPath + Utils::HostOsInfo::withExecutableSuffix("/qtcrashhandler");
}
QtSystemExceptionHandler::~QtSystemExceptionHandler()
{
#ifdef ENABLE_QT_BREAKPAD
delete exceptionHandler;
#endif
}
void QtSystemExceptionHandler::setPlugins(const QStringList &pluginNameList)
{
s_plugins = QString("{%1}").arg(pluginNameList.join(","));
}
void QtSystemExceptionHandler::setBuildVersion(const QString &version)
{
s_buildVersion = version;
}
QString QtSystemExceptionHandler::buildVersion()
{
return s_buildVersion;
}
QString QtSystemExceptionHandler::plugins()
{
return s_plugins;
}
void QtSystemExceptionHandler::setCrashHandlerPath(const QString &crashHandlerPath)
{
s_crashHandlerPath = crashHandlerPath;
}
QString QtSystemExceptionHandler::crashHandlerPath()
{
return s_crashHandlerPath;
}
void QtSystemExceptionHandler::crash()
{
int *a = (int*)0x42;
fprintf(stdout, "Going to crash...\n");
fprintf(stdout, "A = %d", *a);
}
QDateTime QtSystemExceptionHandler::startTime()
{
return s_startTime;
}
/****************************************************************************
**
** Copyright (C) 2017 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
#pragma once
#include <QDateTime>
namespace google_breakpad {
class ExceptionHandler;
}
class QtSystemExceptionHandler
{
public:
QtSystemExceptionHandler(const QString &libexecPath);
~QtSystemExceptionHandler();
static void crash();
static void setPlugins(const QStringList &pluginNameList);
static void setBuildVersion(const QString &version);
static void setCrashHandlerPath(const QString &crashHandlerPath);
static QString plugins();
static QString buildVersion();
static QString crashHandlerPath();
static QDateTime startTime();
protected:
void init(const QString &libexecPath);
private:
google_breakpad::ExceptionHandler *exceptionHandler = nullptr;
};
#!/usr/bin/python
import sys
import os
import os.path
import subprocess
import shlex
import shutil
import base64
from poster.encode import multipart_encode
from poster.encode import MultipartParam
from poster.streaminghttp import register_openers
import urllib2
from optparse import OptionParser
register_openers()
breakpadSourceDir = os.environ['BREAKPAD_SOURCE_DIR']
breakpadUploadUrl = os.environ['BREAKPAD_UPLOAD_URL']
breakpadUserName = os.environ['BREAKPAD_USER_NAME']
breakpadUserPassword = os.environ['BREAKPAD_USER_PASSWORD']
if sys.platform == 'win32':
nullfilename = 'nul:'
else:
nullfilename = '/dev/null'
nullfile = open(nullfilename, 'r+b')
def stdoutFromProcess(process):
(stdout, stderr) = process.communicate()
if stderr:
print stderr
raise SystemError()
sys.exit(1)
return stdout
def toolPath():
if sys.platform == 'linux2':
dumpsymsPath = os.path.join(breakpadSourceDir, 'src/tools/linux/dump_syms/dump_syms')
elif sys.platform == 'darwin':
dumpsymsPath = os.path.join(breakpadSourceDir, 'src/tools/mac/dump_syms/build/Release/dump_syms')
elif sys.platform == 'win32':