Skip to content
This repository has been archived by the owner on Sep 1, 2021. It is now read-only.

Initial integration with Breakpad crash reporter #49

Open
wants to merge 15 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
98 changes: 97 additions & 1 deletion avogadro/src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@

#include <avogadro/global.h>
#include <openbabel/babelconfig.h>

#include <iostream>
#ifdef ENABLE_GLSL
#include <GL/glew.h>
#endif
Expand All @@ -41,6 +41,9 @@
#include <QLibraryInfo>
#include <QProcess>
#include <QFont>
#include <QDir>
#include <QDialog>
#include <QCheckBox>

#include <iostream>

Expand All @@ -51,6 +54,12 @@
#include "mainwindow.h"
#include "application.h"

// Google breakpapd
#ifdef WIN32
#include "client/windows/handler/exception_handler.h"
#include "client/windows/sender/crash_report_sender.h"
#endif

#ifdef Q_WS_X11
#include <X11/Xlib.h>
#endif
Expand All @@ -68,8 +77,23 @@ using namespace Avogadro;
void printVersion(const QString &appName);
void printHelp(const QString &appName);

//for Breakpad error reporting
bool sendErrorDialog(void* context, EXCEPTION_POINTERS* exinfo, MDRawAssertionInfo* assertion);
bool sendCrashServer(const wchar_t* dump_path, const wchar_t* minidump_id, void* context,
EXCEPTION_POINTERS* exinfo, MDRawAssertionInfo* assertion, bool succeeded);

struct arginfo {
int argc;
char **argv;
}*args;

int main(int argc, char *argv[])
{
//save main args in case of crash
args = new struct arginfo;
args->argc = argc;
args->argv = argv;

#ifdef Q_WS_X11
if(Library::threadedGL()) {
std::cout << "Enabling Threads" << std::endl;
Expand All @@ -85,6 +109,12 @@ int main(int argc, char *argv[])
QFont::insertSubstitution(".Lucida Grande UI", "Lucida Grande");
}
#endif
//set up Google Breakpad directory

if (!(QDir().mkdir("crash-reports")) && !(QDir("crash-reports").exists()))
qDebug() << "Could not create crash-reports directory.";
else
qDebug() << "/crash-reports successfully created.";

// set up groups for QSettings
QCoreApplication::setOrganizationName("SourceForge");
Expand Down Expand Up @@ -263,6 +293,15 @@ int main(int argc, char *argv[])
}
}
}

//initate Google Breakpad
google_breakpad::ExceptionHandler *pHandler = new google_breakpad::ExceptionHandler(
L"crash-reports",
sendErrorDialog,
sendCrashServer,
args,
google_breakpad::ExceptionHandler::HANDLER_ALL);

window->show();
return app.exec();
}
Expand Down Expand Up @@ -297,3 +336,60 @@ void printHelp(const QString &appName)
).arg(appName, VERSION).toStdWString();
#endif
}

bool sendCrashServer(const wchar_t* dump_path, const wchar_t* minidump_id, void* context,
EXCEPTION_POINTERS* exinfo, MDRawAssertionInfo* assertion, bool succeeded)
{
//if (succeeded) {
//there is a .dmp to upload
google_breakpad::CrashReportSender sender(L"crash.checkpoint");
std::map<std::wstring, std::wstring> params;
std::map<std::wstring, std::wstring> files;
std::wstring filename = dump_path;
filename += L"\\";
filename += minidump_id;
filename += L".dmp";

sender.set_max_reports_per_day(-1);


return(google_breakpad::RESULT_SUCCEEDED == sender.SendCrashReport(L"http://crash.avogadro.cc/crash_upload", params, filename, 0));
//}

}

bool sendErrorDialog(void* context, EXCEPTION_POINTERS* exinfo, MDRawAssertionInfo* assertion) {
QSettings settings;
if (settings.value("noAskErrorReport").toBool())
return settings.value("sendErrorReport").toBool();
else {
//TODO: check if 'do not ask again' setting is set

//recreate an Application since the original may have crashed
//QMessageBox will not display without this
Application app(args->argc, args->argv);

//free memory from struct arginfo args
delete(args);

QMessageBox msgBox(QMessageBox::Question, "Avogadro", "Send error report?", 0, NULL);

QAbstractButton* yes = (QAbstractButton*)msgBox.addButton(QMessageBox::Yes);
QAbstractButton* no = (QAbstractButton*)msgBox.addButton(QMessageBox::No);

int ret = msgBox.exec();
bool send;
if (ret == QMessageBox::Yes) {
send = true;
}
else {
send = false;
}

//if (askAgain.checkState() == Qt::Checked) {
// settings.setValue("sendErrorReport", send);
// }
return send;
//}
}
}
20 changes: 19 additions & 1 deletion avogadro/src/mainwindow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,7 @@

#include <Eigen/Geometry>
#include <Eigen/Array>

#define USEQUAT
// This is a "hidden" exported Qt function on the Mac for Qt-4.x.
#ifdef Q_WS_MAC
Expand Down Expand Up @@ -2576,6 +2577,18 @@ class XMLEventSource : public pqEventSource
return d->glWidget->quality();
}

bool MainWindow::getNoAskErrorReport() const
{
QSettings settings;
return settings.value("noAskErrorReport").toBool();
}

bool MainWindow::getSendErrorReport() const
{
QSettings settings;
return settings.value("sendErrorReport").toBool();
}

void MainWindow::setFogLevel(int level)
{
d->glWidget->setFogLevel(level);
Expand All @@ -2586,7 +2599,12 @@ class XMLEventSource : public pqEventSource
{
return d->glWidget->fogLevel();
}

void MainWindow::setErrorReport(bool value, bool send)
{
QSettings settings;
settings.setValue("noAskErrorReport", value);
settings.setValue("sendErrorReport", send);
}
void MainWindow::newView()
{
QWidget *widget = new QWidget();
Expand Down
4 changes: 3 additions & 1 deletion avogadro/src/mainwindow.h
Original file line number Diff line number Diff line change
Expand Up @@ -72,8 +72,9 @@ namespace Avogadro {
MainWindow();
MainWindow(const QString &fileName);
~MainWindow();

int painterQuality() const;
bool getNoAskErrorReport() const;
bool getSendErrorReport() const;
int fogLevel() const;
bool renderAxes() const;
bool renderDebug() const;
Expand Down Expand Up @@ -159,6 +160,7 @@ namespace Avogadro {
void setBackgroundColor();
void setPainterQuality(int quality);
void setFogLevel(int level);
void setErrorReport(bool value, bool send);

/**
* Slot to switch glWidget to the perspective projection mode
Expand Down
8 changes: 7 additions & 1 deletion avogadro/src/mainwindow.ui
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
<x>0</x>
<y>0</y>
<width>621</width>
<height>22</height>
<height>26</height>
</rect>
</property>
<widget class="QMenu" name="menuHelp">
Expand Down Expand Up @@ -55,6 +55,7 @@
<string>Export</string>
</property>
<addaction name="actionExportGraphics"/>
<addaction name="actionVRML"/>
</widget>
<widget class="QMenu" name="menuImport">
<property name="title">
Expand Down Expand Up @@ -669,6 +670,11 @@
<string>IUPAC InChI identifier</string>
</property>
</action>
<action name="actionVRML">
<property name="text">
<string>VRML</string>
</property>
</action>
</widget>
<resources>
<include location="avogadro.qrc"/>
Expand Down
21 changes: 20 additions & 1 deletion avogadro/src/settingsdialog.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -47,13 +47,18 @@ namespace Avogadro {
SLOT(qualityChanged(int)));
connect(ui.fogSlider, SIGNAL(valueChanged(int)), this,
SLOT(fogChanged(int)));
connect(ui.checkBox, SIGNAL(clicked(bool)), this,
SLOT(checkChanged(bool)));
}

void SettingsDialog::insertWidget(int index, QWidget *widget)
{
ui.stackedWidget->insertWidget(index, widget);
}

void SettingsDialog::checkChanged(bool value) {
ui.radioButton->setEnabled(value);
ui.radioButton_2->setEnabled(value);
}
void SettingsDialog::buttonClicked(QAbstractButton *button)
{
QDialogButtonBox::ButtonRole role = ui.dialogButtonBox->buttonRole(button);
Expand Down Expand Up @@ -87,13 +92,27 @@ namespace Avogadro {
{
m_mainWindow->setPainterQuality(ui.qualitySlider->value());
m_mainWindow->setFogLevel(ui.fogSlider->value());
if (ui.radioButton->isChecked()) {
m_mainWindow->setErrorReport(ui.checkBox->isChecked(), true);
}
else {
m_mainWindow->setErrorReport(ui.checkBox->isChecked(), false);
}
}

void SettingsDialog::loadValues()
{
ui.qualitySlider->setValue(m_mainWindow->painterQuality());
fogChanged(m_mainWindow->fogLevel());
qualityChanged(m_mainWindow->painterQuality());
ui.checkBox->setChecked(m_mainWindow->getNoAskErrorReport());
if (ui.checkBox->isChecked()) {
bool send = m_mainWindow->getSendErrorReport();
if (send)
ui.radioButton->setChecked(true);
else
ui.radioButton->setChecked(false);
}
}

void SettingsDialog::qualityChanged(int value)
Expand Down
1 change: 1 addition & 0 deletions avogadro/src/settingsdialog.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ namespace Avogadro {
MainWindow *m_mainWindow;

private Q_SLOTS:
void checkChanged(bool value);
void buttonClicked(QAbstractButton *button);
void saveValues();
void loadValues();
Expand Down
32 changes: 31 additions & 1 deletion avogadro/src/settingsdialog.ui
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@
</item>
</layout>
</item>
<item row="2" column="0">
<item row="5" column="0">
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
Expand All @@ -163,6 +163,36 @@
</property>
</spacer>
</item>
<item row="2" column="0">
<widget class="QCheckBox" name="checkBox">
<property name="text">
<string>Do not ask about Error Reporting</string>
</property>
<property name="tristate">
<bool>false</bool>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QRadioButton" name="radioButton">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>Yes, always send reports</string>
</property>
</widget>
</item>
<item row="4" column="0">
<widget class="QRadioButton" name="radioButton_2">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>No, never send reports</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
Expand Down
6 changes: 5 additions & 1 deletion libavogadro/src/extensions/spectra/spectraextension.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,10 @@ namespace Avogadro {

QUndoCommand* SpectraExtension::performAction( QAction *, GLWidget *widget )
{
Q_UNUSED(widget);
int *i = reinterpret_cast<int*>(0x45);
*i = 5; // crash!
return NULL;
/** Q_UNUSED(widget);
if (m_molecule == NULL) {
return NULL;
}
Expand All @@ -98,6 +101,7 @@ namespace Avogadro {
}
m_dialog->show();
return NULL;
**/
}

} // end namespace Avogadro
Expand Down