Browse Source

[COR] Show message, even if the thread crash

master
Ulrich Van Den Hekke 12 years ago
parent
commit
928c7f730c
  1. 1
      framework/application/mainformimpl.cpp
  2. 36
      framework/core/exceptions.cpp
  3. 3
      framework/core/exceptions.h
  4. 12
      framework/core/uniqueapplication.cpp
  5. 2
      framework/core/uniqueapplication.h
  6. 14
      framework/core/xinxthread.cpp
  7. 8
      framework/jobs/xinxjob.cpp
  8. 2
      framework/utils/treeproxyitemmodel.cpp
  9. 24
      xinx/main.cpp

1
framework/application/mainformimpl.cpp

@ -315,6 +315,7 @@ void MainformImpl::createActions()
connect(m_aboutAct, SIGNAL(triggered()), this, SLOT(about()));
// Tab Editor
connect(EditorManager::self(), SIGNAL(currentChanged(int)), this, SLOT(currentTabChanged(int)));
connect(EditorManager::self(), SIGNAL(codecChanged()), this, SLOT(updateEditorInformations()));
connect(EditorManager::self(), SIGNAL(currentChanged(int)), this, SLOT(updateActions()));

36
framework/core/exceptions.cpp

@ -44,6 +44,20 @@
# include <cxxabi.h>
#endif
/* Signal Handler */
static void backup_appli_signal(int signal)
{
std::signal(SIGSEGV, SIG_DFL);
std::signal(SIGABRT, SIG_DFL);
std::signal(SIGINT, SIG_DFL);
std::signal(SIGTERM, SIG_DFL);
const QString thread = QThread::currentThread () == qApp->thread () ? ExceptionManager::tr("GUI") : QString::number ((qulonglong)QThread::currentThreadId (), 16);
const QString message = ExceptionManager::tr("Signal %1 emited in thread %2").arg (signal).arg (thread);
ExceptionManager::self ()->notifyError(message, QtFatalMsg, true);
}
/* Message Handler */
static void xinxMessageHandler(QtMsgType t, const char * m)
@ -109,6 +123,18 @@ void ExceptionManager::installExceptionHandler()
qInstallMsgHandler(xinxMessageHandler);
}
/*!
* \brief Install the signal handler (must be called in each thread) to transform signal into
* exception.
*/
void ExceptionManager::installSignalHandler()
{
std::signal(SIGSEGV, backup_appli_signal);
std::signal(SIGABRT, backup_appli_signal);
std::signal(SIGINT, backup_appli_signal);
std::signal(SIGTERM, backup_appli_signal);
}
/*!
* \brief Stack trace generated by the Operating System. The application must be compiled with
* -rdynamic in Gnu/Linux. This stack is unused on Windows.
@ -165,19 +191,13 @@ void ExceptionManager::notifyError(QString error, QtMsgType t, bool showMessage)
if (t == QtFatalMsg)
{
if (QThread::currentThread() == qApp->thread())
{
QMessageBox::critical(0, qApp->applicationName(),
tr("Oh boy ! A fatal error occur with the message :\n%1\n"
"Please forgive me, i try to recover your work.").arg(error));
}
// On restore les signaux pour eviter d'etre perturbe pendant la phase de sauvegarde ...
std::signal(SIGSEGV, SIG_DFL);
std::signal(SIGABRT, SIG_DFL);
std::signal(SIGINT, SIG_DFL);
std::signal(SIGTERM, SIG_DFL);
emit errorTriggered();
emit errorTriggered(error);
#ifndef _XINX_RELEASE_MODE_
abort();

3
framework/core/exceptions.h

@ -73,10 +73,11 @@ public:
QStringList stackTrace() const;
static void installExceptionHandler();
static void installSignalHandler();
public slots:
void notifyError(QString error, QtMsgType t = QtWarningMsg, bool showMessage = true);
signals:
void errorTriggered();
void errorTriggered(const QString & message);
private:
ExceptionManager();

12
framework/core/uniqueapplication.cpp

@ -77,17 +77,21 @@ void UniqueApplication::attachMainWindow(MainformImpl * mainform)
m_mainform = mainform;
setActivationWindow(m_mainform);
connect(ExceptionManager::self(), SIGNAL(errorTriggered()), this, SLOT(slotErrorTriggered()));
connect(ExceptionManager::self(), SIGNAL(errorTriggered(QString)), this, SLOT(slotErrorTriggered(QString)), Qt::BlockingQueuedConnection);
connect(this, SIGNAL(messageReceived(QString)), EditorManager::self(), SLOT(openFile(QString)));
}
void UniqueApplication::slotErrorTriggered()
void UniqueApplication::slotErrorTriggered(const QString & message)
{
if (m_mainform)
{
// Hide the main widget to prevent user interaction
m_mainform->hide();
XinxSession::SessionManager::self()->createRecoverSession();
}
QMessageBox::critical(0, qApp->applicationName(),
tr("Oh boy ! A fatal error occur with the message :\n%1\n"
"Please forgive me, i try to recover your work.").arg(message));
XinxSession::SessionManager::self()->createRecoverSession();
}

2
framework/core/uniqueapplication.h

@ -43,7 +43,7 @@ public:
void attachMainWindow(MainformImpl * mainform);
public slots:
void slotErrorTriggered();
void slotErrorTriggered(const QString & message);
private:
QPointer<MainformImpl> m_mainform;
};

14
framework/core/xinxthread.cpp

@ -62,13 +62,25 @@ XinxThread::~XinxThread()
void XinxThread::run()
{
ExceptionManager::installSignalHandler ();
{
QMutexLocker locker(&(XinxThreadManager::self()->m_mutex));
XinxThreadManager::self()->m_threadCount++;
emit XinxThreadManager::self()->threadCountChange();
}
threadrun();
try
{
threadrun();
}
catch (const std::exception & e)
{
qCritical (e.what());
}
catch (...)
{
qCritical ("Generic Exception");
}
{
QMutexLocker locker(&(XinxThreadManager::self()->m_mutex));

8
framework/jobs/xinxjob.cpp

@ -113,6 +113,8 @@ void XinxJob::setState(int state)
void XinxJob::run()
{
ExceptionManager::installSignalHandler ();
emit jobStarting();
_count_job.ref();
@ -124,7 +126,11 @@ void XinxJob::run()
}
catch (const std::exception & e)
{
qWarning() << e.what();
qCritical () << e.what();
}
catch (...)
{
qCritical () << tr("Unknown exception");
}
_count_job.deref();
setState(JOB_ENDING);

2
framework/utils/treeproxyitemmodel.cpp

@ -78,7 +78,7 @@
TreeProxyItemModel::TreeProxyItemModel(QObject * parent) : QAbstractProxyModel(parent), m_sourceColumnCount(0), m_resetModel(false)
{
#ifndef _XINX_RELEASE_MODE_
// connect( ExceptionManager::self(), SIGNAL(errorTriggered()), this, SLOT(printMapping()) );
//connect( ExceptionManager::self(), SIGNAL(errorTriggered(QString)), this, SLOT(printMapping()), Qt::BlockingQueuedConnection );
#endif
}

24
xinx/main.cpp

@ -50,7 +50,6 @@
#include <QtPlugin>
// C++ header
#include <csignal>
#include <iostream>
#include <time.h>
@ -59,24 +58,6 @@ Q_IMPORT_PLUGIN(coreplugin);
MainformImpl * mainWin = NULL;
class SignalSegFaultException : public XinxException
{
public:
SignalSegFaultException(int signal) : XinxException(QString("Signal emited : %1").arg(signal))
{
}
};
static void backup_appli_signal(int signal)
{
std::signal(SIGSEGV, SIG_DFL);
std::signal(SIGABRT, SIG_DFL);
std::signal(SIGINT, SIG_DFL);
std::signal(SIGTERM, SIG_DFL);
throw SignalSegFaultException(signal);
}
static void initSearchPath(QApplication * app)
{
const QString configDirectory = QDesktopServices::storageLocation(QDesktopServices::DataLocation);
@ -160,10 +141,7 @@ int main(int argc, char *argv[])
Q_INIT_RESOURCE(application);
qsrand(time(NULL));
std::signal(SIGSEGV, backup_appli_signal);
std::signal(SIGABRT, backup_appli_signal);
std::signal(SIGINT, backup_appli_signal);
std::signal(SIGTERM, backup_appli_signal);
ExceptionManager::installSignalHandler ();
#if defined(Q_WS_WIN)
if (QSysInfo::WindowsVersion >= QSysInfo::WV_VISTA && QSysInfo::WindowsVersion < QSysInfo::WV_NT_based)

Loading…
Cancel
Save