[kwin_wrapper] Port kwin_wrapper to not block

Functionally the same, but will be useful for some pending startup
changes where we have other operations.
This commit is contained in:
David Edmundson 2021-08-10 00:19:36 +01:00
parent f541d851ed
commit ad6ff56468

View file

@ -26,6 +26,8 @@
#include <QTemporaryFile> #include <QTemporaryFile>
#include <signal.h>
#include "wl-socket.h" #include "wl-socket.h"
#include "xwaylandsocket.h" #include "xwaylandsocket.h"
#include "xauthority.h" #include "xauthority.h"
@ -38,17 +40,20 @@ public:
KWinWrapper(QObject *parent); KWinWrapper(QObject *parent);
~KWinWrapper(); ~KWinWrapper();
void run(); void run();
int runKwin();
private: private:
wl_socket *m_socket; wl_socket *m_socket;
int m_crashCount = 0;
QProcess *m_kwinProcess = nullptr;
QScopedPointer<KWin::XwaylandSocket> m_xwlSocket; QScopedPointer<KWin::XwaylandSocket> m_xwlSocket;
QTemporaryFile m_xauthorityFile; QTemporaryFile m_xauthorityFile;
}; };
KWinWrapper::KWinWrapper(QObject *parent) KWinWrapper::KWinWrapper(QObject *parent)
: QObject(parent) : QObject(parent)
, m_kwinProcess(new QProcess(this))
{ {
m_socket = wl_socket_create(); m_socket = wl_socket_create();
if (!m_socket) { if (!m_socket) {
@ -74,38 +79,17 @@ KWinWrapper::KWinWrapper(QObject *parent)
KWinWrapper::~KWinWrapper() KWinWrapper::~KWinWrapper()
{ {
wl_socket_destroy(m_socket); wl_socket_destroy(m_socket);
if (m_kwinProcess) {
m_kwinProcess->terminate();
m_kwinProcess->waitForFinished();
m_kwinProcess->kill();
m_kwinProcess->waitForFinished();
}
} }
void KWinWrapper::run() void KWinWrapper::run()
{ {
int crashCount = 0; m_kwinProcess->setProgram("kwin_wayland");
while (crashCount < 10) {
if (crashCount > 0) {
qputenv("KWIN_RESTART_COUNT", QByteArray::number(crashCount));
}
int exitStatus = runKwin();
if (exitStatus == 133) {
crashCount = 1;
qCDebug(KWIN_WRAPPER) << "Compositor restarted, respawning";
} else if (exitStatus == -1) {
// kwin_crashed, lets go again
qWarning(KWIN_WRAPPER) << "Compositor crashed, respawning";
} else {
qWarning(KWIN_WRAPPER) << "Compositor exited with code: " << exitStatus;
break;
}
}
}
int KWinWrapper::runKwin()
{
qCDebug(KWIN_WRAPPER) << "Launching kwin";
auto process = new QProcess(qApp);
process->setProgram("kwin_wayland");
QStringList args; QStringList args;
@ -126,26 +110,46 @@ int KWinWrapper::runKwin()
// the first entry is dropped as it will be our program name // the first entry is dropped as it will be our program name
args << qApp->arguments().mid(1); args << qApp->arguments().mid(1);
process->setProcessChannelMode(QProcess::ForwardedChannels); m_kwinProcess->setProcessChannelMode(QProcess::ForwardedChannels);
process->setArguments(args); m_kwinProcess->setArguments(args);
process->start();
process->waitForFinished(-1);
if (process->exitStatus() == QProcess::CrashExit) { connect(m_kwinProcess, QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished), this, [this](int exitCode, QProcess::ExitStatus exitStatus) {
return -1; Q_UNUSED(exitStatus)
if (exitCode == 0) {
qApp->quit();
return;
} else if (exitCode == 133) {
m_crashCount = 0;
}
m_crashCount++;
if (m_crashCount > 10) {
qApp->quit();
return;
}
qputenv("KWIN_RESTART_COUNT", QByteArray::number(m_crashCount));
// restart
m_kwinProcess->start();
});
m_kwinProcess->start();
} }
return process->exitCode(); void sigtermHandler(int)
{
qApp->quit();
} }
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
QCoreApplication app(argc, argv); QCoreApplication app(argc, argv);
signal(SIGTERM, sigtermHandler);
KWinWrapper wrapper(&app); KWinWrapper wrapper(&app);
wrapper.run(); wrapper.run();
return 0; return app.exec();
} }
#include "kwin_wrapper.moc" #include "kwin_wrapper.moc"