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(Qt5Quick REQUIRED)
|
||||||
find_package(Qt5Script REQUIRED)
|
find_package(Qt5Script REQUIRED)
|
||||||
find_package(KCoreAddons REQUIRED)
|
find_package(KCoreAddons REQUIRED)
|
||||||
|
find_package(KCrash REQUIRED)
|
||||||
find_package(Solid REQUIRED)
|
find_package(Solid REQUIRED)
|
||||||
find_package(KActivities REQUIRED)
|
find_package(KActivities REQUIRED)
|
||||||
|
|
||||||
@ -64,6 +65,7 @@ target_link_libraries(plasma-shell
|
|||||||
KF5::KIOCore
|
KF5::KIOCore
|
||||||
KF5::KWindowSystem
|
KF5::KWindowSystem
|
||||||
KF5::KCoreAddons
|
KF5::KCoreAddons
|
||||||
|
KF5::KCrash
|
||||||
Plasma
|
Plasma
|
||||||
PlasmaQuick
|
PlasmaQuick
|
||||||
Qt5::Script
|
Qt5::Script
|
||||||
|
@ -36,17 +36,25 @@ int main(int argc, char** argv)
|
|||||||
QApplication app(argc, argv);
|
QApplication app(argc, argv);
|
||||||
app.setApplicationVersion(version);
|
app.setApplicationVersion(version);
|
||||||
|
|
||||||
QCommandLineOption dbg = QCommandLineOption(QStringList() << QStringLiteral("d") << QStringLiteral("qmljsdebugger"),
|
QCommandLineOption dbg = QCommandLineOption(QStringList() << QStringLiteral("d") <<
|
||||||
QStringLiteral("Enable QML Javascript debugger"));
|
QStringLiteral("qmljsdebugger"),
|
||||||
|
QStringLiteral("Enable QML Javascript debugger"));
|
||||||
|
|
||||||
QCommandLineOption windowed = QCommandLineOption(QStringList() << QStringLiteral("w") << QStringLiteral("windowed"),
|
QCommandLineOption windowed = QCommandLineOption(QStringList() << QStringLiteral("w") <<
|
||||||
QStringLiteral("force a windowed view for desktop purposes"));
|
QStringLiteral("windowed"),
|
||||||
|
QStringLiteral("Force a windowed view for testing purposes"));
|
||||||
|
|
||||||
|
QCommandLineOption crashesOption(QStringLiteral("crashes"),
|
||||||
|
QStringLiteral("Recent number of crashes"),
|
||||||
|
QStringLiteral("n"));
|
||||||
|
|
||||||
parser.addVersionOption();
|
parser.addVersionOption();
|
||||||
parser.addHelpOption();
|
parser.addHelpOption();
|
||||||
parser.setApplicationDescription(description);
|
parser.setApplicationDescription(description);
|
||||||
parser.addOption(dbg);
|
parser.addOption(dbg);
|
||||||
parser.addOption(windowed);
|
parser.addOption(windowed);
|
||||||
|
parser.addOption(crashesOption);
|
||||||
|
|
||||||
parser.process(app);
|
parser.process(app);
|
||||||
|
|
||||||
//enable the QML debugger only if --qmljsdebugger (or -d) is passed as a command line arg
|
//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);
|
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::s_forceWindowed = parser.isSet(windowed);
|
||||||
|
|
||||||
ShellManager::instance();
|
ShellManager::instance();
|
||||||
|
|
||||||
return app.exec();
|
return app.exec();
|
||||||
|
@ -26,18 +26,23 @@
|
|||||||
#include <QList>
|
#include <QList>
|
||||||
#include <QTimer>
|
#include <QTimer>
|
||||||
|
|
||||||
|
#include <qplatformdefs.h>
|
||||||
#include <QQmlEngine>
|
#include <QQmlEngine>
|
||||||
#include <QQmlComponent>
|
#include <QQmlComponent>
|
||||||
|
|
||||||
#include <config-prefix.h>
|
#include <config-prefix.h>
|
||||||
#include "shellcorona.h"
|
#include "shellcorona.h"
|
||||||
|
|
||||||
|
#include <kcrash.h>
|
||||||
|
|
||||||
static const QString s_shellsDir(
|
static const QString s_shellsDir(
|
||||||
QString(CMAKE_INSTALL_PREFIX) + "/" + DATA_INSTALL_DIR + "/" + "plasma/shells/");
|
QString(CMAKE_INSTALL_PREFIX) + "/" + DATA_INSTALL_DIR + "/" + "plasma/shells/");
|
||||||
static const QString s_shellLoaderPath = QString("/contents/loader.qml");
|
static const QString s_shellLoaderPath = QString("/contents/loader.qml");
|
||||||
|
|
||||||
bool ShellManager::s_forceWindowed = false;
|
bool ShellManager::s_forceWindowed = false;
|
||||||
|
|
||||||
|
int ShellManager::crashes = 0;
|
||||||
|
|
||||||
//
|
//
|
||||||
// ShellManager
|
// ShellManager
|
||||||
//
|
//
|
||||||
@ -60,6 +65,10 @@ public:
|
|||||||
ShellManager::ShellManager()
|
ShellManager::ShellManager()
|
||||||
: d(new Private())
|
: 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(
|
connect(
|
||||||
&d->shellUpdateDelay, &QTimer::timeout,
|
&d->shellUpdateDelay, &QTimer::timeout,
|
||||||
@ -203,3 +212,39 @@ ShellManager * ShellManager::instance()
|
|||||||
return &manager;
|
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 bool s_forceWindowed;
|
||||||
|
|
||||||
|
static void setCrashCount(int count);
|
||||||
|
|
||||||
protected Q_SLOTS:
|
protected Q_SLOTS:
|
||||||
void registerHandler(QObject * handler);
|
void registerHandler(QObject * handler);
|
||||||
void deregisterHandler(QObject * handler);
|
void deregisterHandler(QObject * handler);
|
||||||
@ -45,11 +47,17 @@ public Q_SLOTS:
|
|||||||
Q_SIGNALS:
|
Q_SIGNALS:
|
||||||
void shellChanged(const QString & shell);
|
void shellChanged(const QString & shell);
|
||||||
|
|
||||||
|
private Q_SLOTS:
|
||||||
|
void resetCrashCount();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
ShellManager();
|
ShellManager();
|
||||||
|
|
||||||
class Private;
|
class Private;
|
||||||
const QScopedPointer<Private> d;
|
const QScopedPointer<Private> d;
|
||||||
|
|
||||||
|
static int crashes;
|
||||||
|
static void crashHandler(int signal);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* SHELLMANAGER_H */
|
#endif /* SHELLMANAGER_H */
|
||||||
|
Loading…
x
Reference in New Issue
Block a user