# HG changeset patch # User sheepluva # Date 1402799634 -7200 # Node ID e13d3147f15b7e1d1934e215f916af9dcb5f4891 # Parent 4fca8bcfaff0751f4c9e313dcd37eab176a6c6b0 do not get stuck on "in game..." page just because of game crash. output a message instead. could still need some tweaking, but a man gotta sleep. and sheep too... diff -r 4fca8bcfaff0 -r e13d3147f15b QTfrontend/game.cpp --- a/QTfrontend/game.cpp Sun Jun 15 00:02:25 2014 +0200 +++ b/QTfrontend/game.cpp Sun Jun 15 04:33:54 2014 +0200 @@ -248,7 +248,12 @@ case 'E': { int size = msg.size(); - emit ErrorMessage(QString("Last two engine messages:\n") + QString().append(msg.mid(2)).left(size - 4)); + emit ErrorMessage( + QString("A Fatal ERROR occured! - The game engine had to stop.") + + "\n\n " + tr("We are very sorry for the inconvenience :(") + + "\n\n" + tr("If this keeps happening, please click the '%1' button in the main menu!") + .arg("Feedback") + "\n\n" + "Last two engine messages:\n" + QString().append(msg.mid(2)).left(size - 4)); return; } case 'i': diff -r 4fca8bcfaff0 -r e13d3147f15b QTfrontend/hwform.cpp --- a/QTfrontend/hwform.cpp Sun Jun 15 00:02:25 2014 +0200 +++ b/QTfrontend/hwform.cpp Sun Jun 15 04:33:54 2014 +0200 @@ -1675,7 +1675,7 @@ connect(game, SIGNAL(CampStateChanged(int)), this, SLOT(UpdateCampaignPageProgress(int))); connect(game, SIGNAL(GameStateChanged(GameState)), this, SLOT(GameStateChanged(GameState))); connect(game, SIGNAL(GameStats(char, const QString &)), ui.pageGameStats, SLOT(GameStats(char, const QString &))); - connect(game, SIGNAL(ErrorMessage(const QString &)), this, SLOT(ShowErrorMessage(const QString &)), Qt::QueuedConnection); + connect(game, SIGNAL(ErrorMessage(const QString &)), this, SLOT(ShowFatalErrorMessage(const QString &)), Qt::QueuedConnection); connect(game, SIGNAL(HaveRecord(RecordType, const QByteArray &)), this, SLOT(GetRecord(RecordType, const QByteArray &))); m_lastDemo = QByteArray(); } @@ -2094,9 +2094,9 @@ } } -void HWForm::ShowErrorMessage(const QString & msg) +void HWForm::ShowFatalErrorMessage(const QString & msg) { - MessageDialog::ShowErrorMessage(msg, this); + MessageDialog::ShowFatalMessage(msg, this); } void HWForm::showFeedbackDialog() diff -r 4fca8bcfaff0 -r e13d3147f15b QTfrontend/hwform.h --- a/QTfrontend/hwform.h Sun Jun 15 00:02:25 2014 +0200 +++ b/QTfrontend/hwform.h Sun Jun 15 04:33:54 2014 +0200 @@ -120,7 +120,7 @@ void StartMPGame(); void GameStateChanged(GameState gameState); void ForcedDisconnect(const QString & reason); - void ShowErrorMessage(const QString &); + void ShowFatalErrorMessage(const QString &); void GetRecord(RecordType type, const QByteArray & record); void CreateNetGame(); void UpdateWeapons(); diff -r 4fca8bcfaff0 -r e13d3147f15b QTfrontend/net/tcpBase.cpp --- a/QTfrontend/net/tcpBase.cpp Sun Jun 15 00:02:25 2014 +0200 +++ b/QTfrontend/net/tcpBase.cpp Sun Jun 15 04:33:54 2014 +0200 @@ -172,7 +172,10 @@ thread->start(); #else process = new QProcess(this); - connect(process, SIGNAL(error(QProcess::ProcessError)), this, SLOT(StartProcessError(QProcess::ProcessError))); + connect(process, SIGNAL(error(QProcess::ProcessError)), + this, SLOT(StartProcessError(QProcess::ProcessError))); + connect(process, SIGNAL(finished(int, QProcess::ExitStatus)), + this, SLOT(onEngineDeath(int, QProcess::ExitStatus))); QStringList arguments = getArguments(); #ifdef QT_DEBUG @@ -198,7 +201,9 @@ #endif emit isReadyNow(); } + IPCSocket->deleteLater(); + IPCSocket = NULL; deleteLater(); } @@ -217,6 +222,37 @@ ClientDisconnect(); } +void TCPBase::onEngineDeath(int exitCode, QProcess::ExitStatus exitStatus) +{ + Q_UNUSED(exitStatus); + + ClientDisconnect(); + + // show error message if there was an error that was not an engine's + // fatal error - because that one already sent a info via IPC + if ((exitCode != 0) && (exitCode != 2)) + { + // inform user that something bad happened + MessageDialog::ShowFatalMessage( + tr("The game engine died unexpectedly!") + + QString("\n(exit code %1)").arg(exitCode) + + "\n\n " + tr("We are very sorry for the inconvenience :(") + "\n\n" + + tr("If this keeps happening, please click the '%1' button in the main menu!") + .arg("Feedback")); + + } + + // cleanup up + if (IPCSocket) + { + IPCSocket->close(); + IPCSocket->deleteLater(); + } + + // plot suicide + deleteLater(); +} + void TCPBase::tcpServerReady() { disconnect(srvsList.first(), SIGNAL(isReadyNow()), this, SLOT(tcpServerReady())); diff -r 4fca8bcfaff0 -r e13d3147f15b QTfrontend/net/tcpBase.h --- a/QTfrontend/net/tcpBase.h Sun Jun 15 00:02:25 2014 +0200 +++ b/QTfrontend/net/tcpBase.h Sun Jun 15 04:33:54 2014 +0200 @@ -88,6 +88,7 @@ void ClientDisconnect(); void ClientRead(); void StartProcessError(QProcess::ProcessError error); + void onEngineDeath(int exitCode, QProcess::ExitStatus exitStatus); void tcpServerReady(); }; diff -r 4fca8bcfaff0 -r e13d3147f15b QTfrontend/util/MessageDialog.cpp --- a/QTfrontend/util/MessageDialog.cpp Sun Jun 15 00:02:25 2014 +0200 +++ b/QTfrontend/util/MessageDialog.cpp Sun Jun 15 04:33:54 2014 +0200 @@ -47,26 +47,26 @@ int MessageDialog::ShowMessage(const QString & title, const QString & msg, QMessageBox::Icon icon, QWidget * parent) { - QMessageBox msgMsg(parent ? parent : HWApplication::activeWindow()); + // if no parent try to use active window + parent = parent ? parent : HWApplication::activeWindow(); + + // didn't work? make child of hwform (e.g. for style and because modal) + if (!parent) + { + try + { + HWApplication * app = dynamic_cast(HWApplication::instance()); + if (app->form) + parent = app->form; + } + catch (...) { /* nothing */ } + } + + QMessageBox msgMsg(parent); msgMsg.setWindowTitle(title != NULL ? title : "Hedgewars"); msgMsg.setText(msg); msgMsg.setIcon(icon); msgMsg.setWindowModality(Qt::WindowModal); - if (!parent) - { - try - { - /* workaround to make sure style is correct - * I'd rather assign the stylesheet to qApp directly (in main.cpp), - * but the current Stylesheet will ruin the look (e.g. map selection) :( - */ - HWApplication * app = dynamic_cast(HWApplication::instance()); - if (app->form) - msgMsg.setStyleSheet(app->form->styleSheet()); - } - catch (...) { /* nothing */ } - } - return msgMsg.exec(); } diff -r 4fca8bcfaff0 -r e13d3147f15b hedgewars/uConsts.pas --- a/hedgewars/uConsts.pas Sun Jun 15 00:02:25 2014 +0200 +++ b/hedgewars/uConsts.pas Sun Jun 15 04:33:54 2014 +0200 @@ -26,15 +26,16 @@ {$INCLUDE "config.inc"} const - HaltNoError = 0; - HaltUsageError = 1; - HaltFatalError = 2; - HaltStartupError = 3; + HaltNoError = 0; + HaltUsageError = 1; + HaltFatalError = 2; + HaltStartupError = 3; + HaltFatalErrorNoIPC = 4; // for automatic tests - HaltTestSuccess = 0; - HaltTestFailed = 10; - HaltTestLuaError = 11; + HaltTestSuccess = 0; + HaltTestFailed = 10; + HaltTestLuaError = 11; sfMax = 1000; diff -r 4fca8bcfaff0 -r e13d3147f15b hedgewars/uIO.pas --- a/hedgewars/uIO.pas Sun Jun 15 00:02:25 2014 +0200 +++ b/hedgewars/uIO.pas Sun Jun 15 04:33:54 2014 +0200 @@ -416,7 +416,11 @@ SendIPC('E' + s); // TODO: should we try to clean more stuff here? SDL_Quit; - halt(HaltFatalError); + + if IPCSock <> nil then + halt(HaltFatalError) + else + halt(HaltFatalErrorNoIPC); end; procedure doPut(putX, putY: LongInt; fromAI: boolean);