Skip to content

Commit

Permalink
libdeng2: Catch uncaught exceptions in de::App
Browse files Browse the repository at this point in the history
Exceptions occurring during the event loop must be caught before
they end up at the application level. The application is terminated
immediately when de::App catches an exception.
  • Loading branch information
skyjake committed Mar 16, 2012
1 parent 9380a53 commit 776ad53
Show file tree
Hide file tree
Showing 9 changed files with 116 additions and 6 deletions.
4 changes: 3 additions & 1 deletion doomsday/engine/portable/src/dd_init.cpp
Expand Up @@ -23,6 +23,8 @@
#include <QApplication>
#include <QSettings>
#include <stdlib.h>
#include <de/App>
#include <de/Log>
#include <de/c_wrapper.h>
#include "de_platform.h"
#include "dd_loop.h"
Expand Down Expand Up @@ -82,7 +84,7 @@ int main(int argc, char** argv)
}

// Application core.
QApplication dengApp(argc, argv, useGUI);
de::App dengApp(argc, argv, useGUI);

// Metadata.
QApplication::setOrganizationDomain("dengine.net");
Expand Down
1 change: 1 addition & 0 deletions doomsday/libdeng2/include/de/App
@@ -0,0 +1 @@
#include "core/app.h"
39 changes: 39 additions & 0 deletions doomsday/libdeng2/include/de/core/app.h
@@ -0,0 +1,39 @@
/*
* The Doomsday Engine Project -- libdeng2
*
* Copyright (c) 2010-2012 Jaakko Keränen <jaakko.keranen@iki.fi>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/

#ifndef LIBDENG2_APP_H
#define LIBDENG2_APP_H

#include <QApplication>

namespace de
{
/**
* Application whose event loop is protected against uncaught exceptions.
* Catches the exception and shuts down the app cleanly.
*/
class App : public QApplication
{
public:
App(int& argc, char** argv, bool useGUI);
bool notify(QObject* receiver, QEvent* event);
};
}

#endif // LIBDENG2_APP_H
4 changes: 2 additions & 2 deletions doomsday/libdeng2/include/de/legacy/legacycore.h
Expand Up @@ -21,7 +21,7 @@
#define LIBDENG2_LEGACYCORE_H

#include "../libdeng2.h"
#include <QApplication>
#include "../App"

namespace de {

Expand All @@ -43,7 +43,7 @@ class LegacyCore : public QObject
*
* @param dengApp Application instance.
*/
LegacyCore(QApplication* dengApp);
LegacyCore(App* dengApp);

~LegacyCore();

Expand Down
13 changes: 13 additions & 0 deletions doomsday/libdeng2/include/de/libdeng2.h
Expand Up @@ -28,6 +28,10 @@
# define DENG2_USE_QT
#endif

#if defined(__x86_64__) || defined(__x86_64) || defined(_LP64)
# define DENG2_64BIT
#endif

#ifdef DENG2_USE_QT
#include <QtCore/qglobal.h>
#endif
Expand All @@ -52,12 +56,14 @@
#endif

#ifndef NDEBUG
# define DENG2_DEBUG
# ifdef DENG2_USE_QT
# define DENG2_ASSERT(x) Q_ASSERT(x)
# else
# define DENG2_ASSERT(x) assert(x)
# endif
#else
# define DENG2_NO_DEBUG
# define DENG2_ASSERT(x)
#endif

Expand Down Expand Up @@ -114,6 +120,13 @@ typedef quint64 duint64; ///< 64-bit unsigned integer.
typedef float dfloat; ///< 32-bit floating point number.
typedef qreal ddouble; ///< 64-bit floating point number.
typedef quint64 dsize;

// Pointer-integer conversion (used for legacy code).
#ifdef DENG2_64BIT
typedef duint64 dintptr;
#else
typedef duint32 dintptr;
#endif
//@}

} // namespace de
Expand Down
3 changes: 3 additions & 0 deletions doomsday/libdeng2/libdeng2.pro
Expand Up @@ -36,6 +36,7 @@ include(network.pri)

# Convenience headers.
HEADERS += \
include/de/App \
include/de/Error \
include/de/Log \
include/de/LogBuffer \
Expand All @@ -44,6 +45,7 @@ HEADERS += \
include/de/c_wrapper.h \
include/de/error.h \
include/de/libdeng2.h \
include/de/core/app.h \
include/de/core/log.h \
include/de/core/logbuffer.h

Expand All @@ -53,6 +55,7 @@ HEADERS += \

SOURCES += \
src/c_wrapper.cpp \
src/core/app.cpp \
src/core/log.cpp \
src/core/logbuffer.cpp

Expand Down
2 changes: 1 addition & 1 deletion doomsday/libdeng2/src/c_wrapper.cpp
Expand Up @@ -29,7 +29,7 @@

LegacyCore* LegacyCore_New(void* dengApp)
{
return reinterpret_cast<LegacyCore*>(new de::LegacyCore(reinterpret_cast<QApplication*>(dengApp)));
return reinterpret_cast<LegacyCore*>(new de::LegacyCore(reinterpret_cast<de::App*>(dengApp)));
}

int LegacyCore_RunEventLoop(LegacyCore* lc)
Expand Down
46 changes: 46 additions & 0 deletions doomsday/libdeng2/src/core/app.cpp
@@ -0,0 +1,46 @@
/*
* The Doomsday Engine Project -- libdeng2
*
* Copyright (c) 2010-2012 Jaakko Keränen <jaakko.keranen@iki.fi>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/

#include "de/App"
#include "de/Log"
#include <QDebug>

using namespace de;

App::App(int& argc, char** argv, bool useGUI) : QApplication(argc, argv, useGUI)
{}

bool App::notify(QObject* receiver, QEvent* event)
{
try
{
return QApplication::notify(receiver, event);
}
catch(const std::exception& error)
{
qWarning() << "de::App caught exception:" << error.what();
::exit(1);
}
catch(...)
{
qWarning() << "de::App caught exception.";
::exit(1);
}
return false;
}
10 changes: 8 additions & 2 deletions doomsday/libdeng2/src/legacy/legacycore.cpp
Expand Up @@ -23,6 +23,7 @@

#include <QCoreApplication>
#include <QTimer>
#include <QDebug>

using namespace de;

Expand All @@ -33,7 +34,7 @@ LegacyCore* LegacyCore::_appCore;
*/
struct LegacyCore::Instance
{
QApplication* app;
App* app;
LegacyNetwork network;
void (*loopFunc)(void);
LogBuffer logBuffer;
Expand All @@ -43,7 +44,7 @@ struct LegacyCore::Instance
~Instance() {}
};

LegacyCore::LegacyCore(QApplication* dengApp)
LegacyCore::LegacyCore(App* dengApp)
{
_appCore = this;
d = new Instance;
Expand All @@ -53,6 +54,9 @@ LegacyCore::LegacyCore(QApplication* dengApp)

// The global log buffer will be available for the entire runtime of deng2.
LogBuffer::setAppBuffer(d->logBuffer);
#ifdef DENG2_DEBUG
d->logBuffer.enable(Log::DEBUG);
#endif
}

LegacyCore::~LegacyCore()
Expand All @@ -77,6 +81,8 @@ LegacyNetwork& LegacyCore::network()

void LegacyCore::setLoopFunc(void (*func)(void))
{
LOG_DEBUG("Loop function changed from %p set to %p.") << (dintptr)d->loopFunc << (dintptr)func;

// Set up a timer to periodically call the provided callback function.
d->loopFunc = func;

Expand Down

0 comments on commit 776ad53

Please sign in to comment.