[plasma/kwin] src: wayland: fix fd leak when starting the input method
Vlad Zahorodnii <[email protected]>
| Newsgroups | gmane.comp.kde.cvs |
|---|---|
| Message-ID | <[email protected]> |
Git commit d4e2c064709a6819ee0e8d1aa7cf37e56566712e by Vlad Zahorodnii, on behalf of zhang shoucheng.
Committed on 14/08/2026 at 05:52.
Pushed by vladz into branch 'master'.
wayland: fix fd leak when starting the input method
The socketpair file descriptor was overwritten by dup() and never closed,
leaking one file descriptor every time the input method server was started
or restarted. Close the original descriptor right after duplicating it,
and destroy the input method connection if dup() fails.
M +15 -2 src/inputmethod.cpp
https://invent.kde.org/plasma/kwin/-/commit/d4e2c064709a6819ee0e8d1aa7cf37e56566712e
diff --git a/src/inputmethod.cpp b/src/inputmethod.cpp
index bdd2eeea4cc..1ec6ced6bf9 100644
--- a/src/inputmethod.cpp
+++ b/src/inputmethod.cpp
@@ -47,6 +47,7 @@
#include <QKeyEvent>
#include <QMenu>
+#include <fcntl.h>
#include <linux/input-event-codes.h>
#include <private/qxkbcommon_p.h>
#include <unistd.h>
@@ -868,12 +869,11 @@ void InputMethod::startInputMethod()
}
const QString program = arguments.takeFirst();
- int socket = waylandServer()->createInputMethodConnection();
+ const int socket = waylandServer()->createInputMethodConnection();
if (socket < 0) {
qWarning("Failed to create the input method connection");
return;
}
- socket = dup(socket);
QProcessEnvironment environment = kwinApp()->processStartupEnvironment();
environment.insert(QStringLiteral("WAYLAND_SOCKET"), QString::number(socket));
@@ -892,6 +892,19 @@ void InputMethod::startInputMethod()
m_inputMethodProcess->setProcessEnvironment(environment);
m_inputMethodProcess->setProgram(program);
m_inputMethodProcess->setArguments(arguments);
+ // The socketpair end is created with CLOEXEC, so the input method process can't inherit
+ // it directly. Clear the flag in the child process right before exec so the input method
+ // process can use the socket; the parent closes its copy after start().
+ m_inputMethodProcess->setChildProcessModifier([this, socket]() {
+ const int originalFlags = fcntl(socket, F_GETFD);
+ if (originalFlags < 0) {
+ m_inputMethodProcess->failChildProcessModifier("failed to get file descriptor flags", errno);
+ return;
+ }
+ if (fcntl(socket, F_SETFD, originalFlags & ~FD_CLOEXEC) < 0) {
+ m_inputMethodProcess->failChildProcessModifier("failed to unset O_CLOEXEC", errno);
+ }
+ });
m_inputMethodProcess->start();
close(socket);
connect(m_inputMethodProcess, QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished), this, [this](int exitCode, QProcess::ExitStatus exitStatus) {