Port away from KToolInvocation

The problem with KToolInvocation is that it creates a dead lock on
Wayland in case kdeinit is not already running. It starts kdeinit
and does a QProcess::waitForFinished and our kdeinit needs to interact
with the wayland server. So dead lock.

As KRun also calls into the dangerous code path it's no option which
leaves us with QProcess to start the processes.

A nice side-effect is that we no don't need to link KF5::Service any
more from kwin_core. Now once Plasma and Notification don't use it
any more, it will be gone completely.
icc-effect-5.14.5
Martin Gräßlin 2015-07-07 17:35:57 +02:00
parent da4305c2fa
commit f6458fa1e8
8 changed files with 43 additions and 13 deletions

View File

@ -72,7 +72,6 @@ find_package(KF5 ${KF5_MIN_VERSION} REQUIRED COMPONENTS
I18n
Init
Notifications
Service
Package
Plasma
WidgetsAddons
@ -86,6 +85,7 @@ find_package(KF5 ${KF5_MIN_VERSION} REQUIRED COMPONENTS
KCMUtils
KIO
NewStuff
Service
XmlGui
)
@ -502,7 +502,6 @@ set(kwin_KDE_LIBS
KF5::GlobalAccelPrivate
KF5::I18n
KF5::Notifications
KF5::Service
KF5::Package
KF5::Plasma
KF5::WindowSystem

View File

@ -7,6 +7,7 @@
#define KWIN_VERSION_STRING "${PROJECT_VERSION}"
#define XCB_VERSION_STRING "${XCB_VERSION}"
#define KWIN_KILLER_BIN "${CMAKE_INSTALL_PREFIX}/${LIBEXEC_INSTALL_DIR}/kwin_killer_helper"
#define KWIN_RULES_DIALOG_BIN "${CMAKE_INSTALL_PREFIX}/${LIBEXEC_INSTALL_DIR}/kwin_rules_dialog"
#cmakedefine01 HAVE_WAYLAND
#cmakedefine01 HAVE_WAYLAND_EGL
#cmakedefine01 HAVE_WAYLAND_CURSOR

View File

@ -533,6 +533,11 @@ bool Application::usesLibinput()
return s_useLibinput;
}
QProcessEnvironment Application::processStartupEnvironment() const
{
return QProcessEnvironment::systemEnvironment();
}
} // namespace
#include "main.moc"

3
main.h
View File

@ -30,6 +30,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
// Qt
#include <QApplication>
#include <QAbstractNativeEventFilter>
#include <QProcessEnvironment>
class QCommandLineParser;
@ -141,6 +142,8 @@ public:
return m_connection;
}
virtual QProcessEnvironment processStartupEnvironment() const;
static void setupMalloc();
static void setupLocalizedString();
static void setupLoggingCategoryFilters();

View File

@ -189,15 +189,14 @@ void ApplicationWayland::continueStartupWithX()
}
}
m_environment.insert(QStringLiteral("DISPLAY"), QString::fromUtf8(qgetenv("DISPLAY")));
// start the applications passed to us as command line arguments
if (!m_applicationsToStart.isEmpty()) {
QProcessEnvironment environment = m_environment;
environment.insert(QStringLiteral("DISPLAY"), QString::fromUtf8(qgetenv("DISPLAY")));
for (const QString &application: m_applicationsToStart) {
// note: this will kill the started process when we exit
// this is going to happen anyway as we are the wayland and X server the app connects to
QProcess *p = new QProcess(this);
p->setProcessEnvironment(environment);
p->setProcessEnvironment(m_environment);
p->start(application);
}
}

View File

@ -50,6 +50,10 @@ public:
bool notify(QObject *o, QEvent *e) override;
QProcessEnvironment processStartupEnvironment() const override {
return m_environment;
}
protected:
void performStartup() override;

View File

@ -27,7 +27,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include <QTemporaryFile>
#include <QFile>
#include <QFileInfo>
#include <ktoolinvocation.h>
#include <QDebug>
#ifndef KCMRULES
@ -995,7 +994,19 @@ void RuleBook::edit(AbstractClient* c, bool whole_app)
args << QStringLiteral("--wid") << QString::number(c->window());
if (whole_app)
args << QStringLiteral("--whole-app");
KToolInvocation::kdeinitExec(QStringLiteral("kwin_rules_dialog"), args);
QProcess *p = new QProcess(this);
p->setArguments(args);
p->setProcessEnvironment(kwinApp()->processStartupEnvironment());
p->setProgram(QStringLiteral(KWIN_RULES_DIALOG_BIN));
connect(p, static_cast<void (QProcess::*)(int, QProcess::ExitStatus)>(&QProcess::finished), this, &QProcess::deleteLater);
connect(p, static_cast<void (QProcess::*)(QProcess::ProcessError)>(&QProcess::error), this,
[p] (QProcess::ProcessError e) {
if (e == QProcess::FailedToStart) {
qCDebug(KWIN_CORE) << "Failed to start kwin_rules_dialog";
}
}
);
p->start();
}
void RuleBook::load()

View File

@ -47,7 +47,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#endif
#include <KProcess>
#include <KToolInvocation>
#include <QAction>
#include <QCheckBox>
@ -307,14 +306,23 @@ void UserActionsMenu::init()
"Window &Manager Settings..."));
action->setIcon(QIcon::fromTheme(QStringLiteral("configure")));
connect(action, &QAction::triggered, this,
[]() {
[this]() {
// opens the KWin configuration
QStringList args;
args << QStringLiteral("--icon") << QStringLiteral("preferences-system-windows") << configModules(false);
QString error;
if (KToolInvocation::kdeinitExec(QStringLiteral("kcmshell5"), args, &error) != 0) {
qCDebug(KWIN_CORE) << "Failed to start kcmshell5: " << error;
}
QProcess *p = new QProcess(this);
p->setArguments(args);
p->setProcessEnvironment(kwinApp()->processStartupEnvironment());
p->setProgram(QStringLiteral("kcmshell5"));
connect(p, static_cast<void (QProcess::*)(int, QProcess::ExitStatus)>(&QProcess::finished), this, &QProcess::deleteLater);
connect(p, static_cast<void (QProcess::*)(QProcess::ProcessError)>(&QProcess::error), this,
[p] (QProcess::ProcessError e) {
if (e == QProcess::FailedToStart) {
qCDebug(KWIN_CORE) << "Failed to start kcmshell5";
}
}
);
p->start();
}
);
}