diff --git a/CMakeLists.txt b/CMakeLists.txt --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -485,7 +485,6 @@ KF5::ConfigCore KF5::CoreAddons KF5::ConfigWidgets - KF5::Crash KF5::GlobalAccel KF5::GlobalAccelPrivate KF5::I18n @@ -570,7 +569,7 @@ endif() kf5_add_kdeinit_executable(kwin_x11 main_x11.cpp) -target_link_libraries(kdeinit_kwin_x11 kwin) +target_link_libraries(kdeinit_kwin_x11 kwin KF5::Crash) install(TARGETS kwin ${INSTALL_TARGETS_DEFAULT_ARGS} LIBRARY NAMELINK_SKIP ) install(TARGETS kdeinit_kwin_x11 ${INSTALL_TARGETS_DEFAULT_ARGS} ) diff --git a/main.h b/main.h --- a/main.h +++ b/main.h @@ -185,7 +185,6 @@ protected: Application(OperationMode mode, int &argc, char **argv); virtual void performStartup() = 0; - virtual void setupCrashHandler(); void notifyKSplash(); void createInput(); @@ -213,16 +212,14 @@ } void destroyAtoms(); - static void crashHandler(int signal); - protected: QString m_originalSessionKey; + static int crashes; private Q_SLOTS: void resetCrashesCount(); private: - void crashChecking(); QScopedPointer m_eventFilter; bool m_configLock; KSharedConfigPtr m_config; @@ -234,7 +231,6 @@ bool m_useKActivities = true; #endif Platform *m_platform = nullptr; - static int crashes; }; inline static Application *kwinApp() diff --git a/main.cpp b/main.cpp --- a/main.cpp +++ b/main.cpp @@ -36,23 +36,14 @@ // KDE #include -#include -#include -#include #include #include #include // Qt #include -#include #include -#include -#include -#include -#include #include #include -#include #include // system @@ -80,52 +71,6 @@ int screen_number = -1; bool is_multihead = false; -class AlternativeWMDialog : public QDialog -{ -public: - AlternativeWMDialog() - : QDialog() { - QWidget* mainWidget = new QWidget(this); - QVBoxLayout* layout = new QVBoxLayout(mainWidget); - QString text = i18n( - "KWin is unstable.\n" - "It seems to have crashed several times in a row.\n" - "You can select another window manager to run:"); - QLabel* textLabel = new QLabel(text, mainWidget); - layout->addWidget(textLabel); - wmList = new QComboBox(mainWidget); - wmList->setEditable(true); - layout->addWidget(wmList); - - addWM(QStringLiteral("metacity")); - addWM(QStringLiteral("openbox")); - addWM(QStringLiteral("fvwm2")); - addWM(QStringLiteral(KWIN_INTERNAL_NAME_X11)); - - QVBoxLayout *mainLayout = new QVBoxLayout(this); - mainLayout->addWidget(mainWidget); - QDialogButtonBox *buttons = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel, this); - buttons->button(QDialogButtonBox::Ok)->setDefault(true); - connect(buttons, &QDialogButtonBox::accepted, this, &QDialog::accept); - connect(buttons, &QDialogButtonBox::rejected, this, &QDialog::reject); - mainLayout->addWidget(buttons); - - raise(); - } - - void addWM(const QString& wm) { - // TODO: Check if WM is installed - if (!QStandardPaths::findExecutable(wm).isEmpty()) - wmList->addItem(wm); - } - QString selectedWM() const { - return wmList->currentText(); - } - -private: - QComboBox* wmList; -}; - int Application::crashes = 0; bool Application::isX11MultiHead() @@ -196,8 +141,6 @@ m_config->reparseConfiguration(); } - crashChecking(); - performStartup(); } @@ -213,55 +156,6 @@ atoms = nullptr; } -void Application::setupCrashHandler() -{ - KCrash::setEmergencySaveFunction(Application::crashHandler); -} - -void Application::crashChecking() -{ - setupCrashHandler(); - if (crashes >= 4) { - // Something has gone seriously wrong - AlternativeWMDialog dialog; - QString cmd = QStringLiteral(KWIN_INTERNAL_NAME_X11); - if (dialog.exec() == QDialog::Accepted) - cmd = dialog.selectedWM(); - else - ::exit(1); - if (cmd.length() > 500) { - qCDebug(KWIN_CORE) << "Command is too long, truncating"; - cmd = cmd.left(500); - } - qCDebug(KWIN_CORE) << "Starting" << cmd << "and exiting"; - char buf[1024]; - sprintf(buf, "%s &", cmd.toAscii().data()); - system(buf); - ::exit(1); - } - if (crashes >= 2) { - // Disable compositing if we have had too many crashes - qCDebug(KWIN_CORE) << "Too many crashes recently, disabling compositing"; - KConfigGroup compgroup(KSharedConfig::openConfig(), "Compositing"); - compgroup.writeEntry("Enabled", false); - } - // Reset crashes count if we stay up for more that 15 seconds - QTimer::singleShot(15 * 1000, this, SLOT(resetCrashesCount())); -} - -void Application::crashHandler(int signal) -{ - 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); - - sleep(1); - system(cmd); -} - void Application::resetCrashesCount() { crashes = 0; diff --git a/main_wayland.h b/main_wayland.h --- a/main_wayland.h +++ b/main_wayland.h @@ -56,7 +56,6 @@ protected: void performStartup() override; - void setupCrashHandler() override; private: void createBackend(); diff --git a/main_wayland.cpp b/main_wayland.cpp --- a/main_wayland.cpp +++ b/main_wayland.cpp @@ -123,12 +123,6 @@ createBackend(); } -void ApplicationWayland::setupCrashHandler() -{ - // this disables auto-restart of kwin_wayland - // do nothing hence allowing OS to create dump and so on -} - void ApplicationWayland::createBackend() { connect(platform(), &Platform::screensQueried, this, &ApplicationWayland::continueStartupWithScreens); diff --git a/main_x11.h b/main_x11.h --- a/main_x11.h +++ b/main_x11.h @@ -56,6 +56,11 @@ void lostSelection(); private: + void crashChecking(); + void setupCrashHandler(); + + static void crashHandler(int signal); + QScopedPointer owner; bool m_replace; }; diff --git a/main_x11.cpp b/main_x11.cpp --- a/main_x11.cpp +++ b/main_x11.cpp @@ -28,27 +28,86 @@ #include "xcbutils.h" // KDE +#include +#include #include #include #include // Qt #include +#include #include +#include +#include +#include +#include +#include +#include // system #ifdef HAVE_UNISTD_H #include #endif // HAVE_UNISTD_H #include +Q_LOGGING_CATEGORY(KWIN_CORE, "kwin_core", QtCriticalMsg) + namespace KWin { static void sighandler(int) { QApplication::exit(); } + + +class AlternativeWMDialog : public QDialog +{ +public: + AlternativeWMDialog() + : QDialog() { + QWidget* mainWidget = new QWidget(this); + QVBoxLayout* layout = new QVBoxLayout(mainWidget); + QString text = i18n( + "KWin is unstable.\n" + "It seems to have crashed several times in a row.\n" + "You can select another window manager to run:"); + QLabel* textLabel = new QLabel(text, mainWidget); + layout->addWidget(textLabel); + wmList = new QComboBox(mainWidget); + wmList->setEditable(true); + layout->addWidget(wmList); + + addWM(QStringLiteral("metacity")); + addWM(QStringLiteral("openbox")); + addWM(QStringLiteral("fvwm2")); + addWM(QStringLiteral(KWIN_INTERNAL_NAME_X11)); + + QVBoxLayout *mainLayout = new QVBoxLayout(this); + mainLayout->addWidget(mainWidget); + QDialogButtonBox *buttons = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel, this); + buttons->button(QDialogButtonBox::Ok)->setDefault(true); + connect(buttons, &QDialogButtonBox::accepted, this, &QDialog::accept); + connect(buttons, &QDialogButtonBox::rejected, this, &QDialog::reject); + mainLayout->addWidget(buttons); + + raise(); + } + + void addWM(const QString& wm) { + // TODO: Check if WM is installed + if (!QStandardPaths::findExecutable(wm).isEmpty()) + wmList->addItem(wm); + } + QString selectedWM() const { + return wmList->currentText(); + } + +private: + QComboBox* wmList; +}; + //************************************ // KWinSelectionOwner //************************************ @@ -149,6 +208,8 @@ void ApplicationX11::performStartup() { + crashChecking(); + if (Application::x11ScreenNumber() == -1) { Application::setX11ScreenNumber(QX11Info::appScreen()); } @@ -215,6 +276,55 @@ return QApplication::notify(o, e); } +void ApplicationX11::setupCrashHandler() +{ + KCrash::setEmergencySaveFunction(ApplicationX11::crashHandler); +} + +void ApplicationX11::crashChecking() +{ + setupCrashHandler(); + if (crashes >= 4) { + // Something has gone seriously wrong + AlternativeWMDialog dialog; + QString cmd = QStringLiteral(KWIN_INTERNAL_NAME_X11); + if (dialog.exec() == QDialog::Accepted) + cmd = dialog.selectedWM(); + else + ::exit(1); + if (cmd.length() > 500) { + qCDebug(KWIN_CORE) << "Command is too long, truncating"; + cmd = cmd.left(500); + } + qCDebug(KWIN_CORE) << "Starting" << cmd << "and exiting"; + char buf[1024]; + sprintf(buf, "%s &", cmd.toAscii().data()); + system(buf); + ::exit(1); + } + if (crashes >= 2) { + // Disable compositing if we have had too many crashes + qCDebug(KWIN_CORE) << "Too many crashes recently, disabling compositing"; + KConfigGroup compgroup(KSharedConfig::openConfig(), "Compositing"); + compgroup.writeEntry("Enabled", false); + } + // Reset crashes count if we stay up for more that 15 seconds + QTimer::singleShot(15 * 1000, this, SLOT(resetCrashesCount())); +} + +void ApplicationX11::crashHandler(int signal) +{ + 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); + + sleep(1); + system(cmd); +} + } // namespace extern "C"