Crash recovery for plasma-shell
We restart plasma-shell after crashes. When it crashes subsequently on startup, and more than two times in a row, we give up in order to not endlessly loop. Once the shell process stays alive for at least 15 seconds, we reset the crash counter, so a later crash, at runtime rather than on startup will still be recovered from. This logic is very similar as to how kwin handles it. DIGEST:
This commit is contained in:
parent
5540fdeaa5
commit
ff40813454
@ -15,6 +15,7 @@ find_package(Qt5Qml REQUIRED)
|
||||
find_package(Qt5Quick REQUIRED)
|
||||
find_package(Qt5Script REQUIRED)
|
||||
find_package(KCoreAddons REQUIRED)
|
||||
find_package(KCrash REQUIRED)
|
||||
find_package(Solid REQUIRED)
|
||||
find_package(KActivities REQUIRED)
|
||||
|
||||
@ -64,6 +65,7 @@ target_link_libraries(plasma-shell
|
||||
KF5::KIOCore
|
||||
KF5::KWindowSystem
|
||||
KF5::KCoreAddons
|
||||
KF5::KCrash
|
||||
Plasma
|
||||
PlasmaQuick
|
||||
Qt5::Script
|
||||
|
@ -36,17 +36,25 @@ int main(int argc, char** argv)
|
||||
QApplication app(argc, argv);
|
||||
app.setApplicationVersion(version);
|
||||
|
||||
QCommandLineOption dbg = QCommandLineOption(QStringList() << QStringLiteral("d") << QStringLiteral("qmljsdebugger"),
|
||||
QStringLiteral("Enable QML Javascript debugger"));
|
||||
QCommandLineOption dbg = QCommandLineOption(QStringList() << QStringLiteral("d") <<
|
||||
QStringLiteral("qmljsdebugger"),
|
||||
QStringLiteral("Enable QML Javascript debugger"));
|
||||
|
||||
QCommandLineOption windowed = QCommandLineOption(QStringList() << QStringLiteral("w") << QStringLiteral("windowed"),
|
||||
QStringLiteral("force a windowed view for desktop purposes"));
|
||||
QCommandLineOption windowed = QCommandLineOption(QStringList() << QStringLiteral("w") <<
|
||||
QStringLiteral("windowed"),
|
||||
QStringLiteral("Force a windowed view for testing purposes"));
|
||||
|
||||
QCommandLineOption crashesOption(QStringLiteral("crashes"),
|
||||
QStringLiteral("Recent number of crashes"),
|
||||
QStringLiteral("n"));
|
||||
|
||||
parser.addVersionOption();
|
||||
parser.addHelpOption();
|
||||
parser.setApplicationDescription(description);
|
||||
parser.addOption(dbg);
|
||||
parser.addOption(windowed);
|
||||
parser.addOption(crashesOption);
|
||||
|
||||
parser.process(app);
|
||||
|
||||
//enable the QML debugger only if --qmljsdebugger (or -d) is passed as a command line arg
|
||||
@ -56,16 +64,9 @@ int main(int argc, char** argv)
|
||||
}
|
||||
|
||||
Plasma::PluginLoader::setPluginLoader(new ShellPluginLoader);
|
||||
// DesktopCorona *corona = new DesktopCorona();
|
||||
// corona->loadLayout();
|
||||
// if (corona->containments().isEmpty()) {
|
||||
// corona->loadDefaultLayout();
|
||||
// }
|
||||
// corona->processUpdateScripts();
|
||||
// corona->checkScreens();
|
||||
|
||||
ShellManager::setCrashCount(parser.value(crashesOption).toInt());
|
||||
ShellManager::s_forceWindowed = parser.isSet(windowed);
|
||||
|
||||
ShellManager::instance();
|
||||
|
||||
return app.exec();
|
||||
|
@ -26,18 +26,23 @@
|
||||
#include <QList>
|
||||
#include <QTimer>
|
||||
|
||||
#include <qplatformdefs.h>
|
||||
#include <QQmlEngine>
|
||||
#include <QQmlComponent>
|
||||
|
||||
#include <config-prefix.h>
|
||||
#include "shellcorona.h"
|
||||
|
||||
#include <kcrash.h>
|
||||
|
||||
static const QString s_shellsDir(
|
||||
QString(CMAKE_INSTALL_PREFIX) + "/" + DATA_INSTALL_DIR + "/" + "plasma/shells/");
|
||||
static const QString s_shellLoaderPath = QString("/contents/loader.qml");
|
||||
|
||||
bool ShellManager::s_forceWindowed = false;
|
||||
|
||||
int ShellManager::crashes = 0;
|
||||
|
||||
//
|
||||
// ShellManager
|
||||
//
|
||||
@ -60,6 +65,10 @@ public:
|
||||
ShellManager::ShellManager()
|
||||
: d(new Private())
|
||||
{
|
||||
// Using setCrashHandler, we end up in an infinite loop instead of quitting,
|
||||
// use setEmergencySaveFunction instead to avoid this.
|
||||
KCrash::setEmergencySaveFunction(ShellManager::crashHandler);
|
||||
QTimer::singleShot(15 * 1000, this, SLOT(resetCrashCount()));
|
||||
|
||||
connect(
|
||||
&d->shellUpdateDelay, &QTimer::timeout,
|
||||
@ -203,3 +212,39 @@ ShellManager * ShellManager::instance()
|
||||
return &manager;
|
||||
}
|
||||
|
||||
void ShellManager::setCrashCount(int count)
|
||||
{
|
||||
crashes = count;
|
||||
}
|
||||
|
||||
void ShellManager::resetCrashCount()
|
||||
{
|
||||
crashes = 0;
|
||||
}
|
||||
|
||||
void ShellManager::crashHandler(int signal)
|
||||
{
|
||||
/* plasma-shell restart logic as crash recovery
|
||||
*
|
||||
* We restart plasma-shell after crashes. When it crashes subsequently on startup,
|
||||
* and more than two times in a row, we give up in order to not endlessly loop.
|
||||
* Once the shell process stays alive for at least 15 seconds, we reset the crash
|
||||
* counter, so a later crash, at runtime rather than on startup will still be
|
||||
* recovered from.
|
||||
*
|
||||
* This logic is very similar as to how kwin handles it.
|
||||
*/
|
||||
crashes++;
|
||||
fprintf(stderr, "Application::crashHandler() called with signal %d; recent crashes: %d\n", signal, crashes);
|
||||
char cmd[1024];
|
||||
sprintf(cmd, "%s --crashes %d &",
|
||||
QFile::encodeName(QCoreApplication::applicationFilePath()).constData(), crashes);
|
||||
|
||||
if (crashes < 3) {
|
||||
sleep(1);
|
||||
system(cmd);
|
||||
} else {
|
||||
fprintf(stderr, "Too many crashes in short order, not restarting automatically.\n");
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -34,6 +34,8 @@ public:
|
||||
|
||||
static bool s_forceWindowed;
|
||||
|
||||
static void setCrashCount(int count);
|
||||
|
||||
protected Q_SLOTS:
|
||||
void registerHandler(QObject * handler);
|
||||
void deregisterHandler(QObject * handler);
|
||||
@ -45,11 +47,17 @@ public Q_SLOTS:
|
||||
Q_SIGNALS:
|
||||
void shellChanged(const QString & shell);
|
||||
|
||||
private Q_SLOTS:
|
||||
void resetCrashCount();
|
||||
|
||||
private:
|
||||
ShellManager();
|
||||
|
||||
class Private;
|
||||
const QScopedPointer<Private> d;
|
||||
|
||||
static int crashes;
|
||||
static void crashHandler(int signal);
|
||||
};
|
||||
|
||||
#endif /* SHELLMANAGER_H */
|
||||
|
Loading…
x
Reference in New Issue
Block a user