https://bugs.kde.org/show_bug.cgi?id=515465
Bug ID: 515465
Summary: xdg-desktop-portal-kde crashes with SIGSEGV when
clipboard data requested by Klipper (Qt threading
violation)
Classification: Plasma
Product: xdg-desktop-portal-kde
Version First 6.5.5
Reported In:
Platform: openSUSE
OS: Linux
Status: REPORTED
Severity: critical
Priority: NOR
Component: general
Assignee: [email protected]
Reporter: [email protected]
CC: [email protected]
Target Milestone: ---
SUMMARY
xdg-desktop-portal-kde crashes with SIGSEGV when clipboard data requested by
Klipper (Qt threading violation)
STEPS TO REPRODUCE
Use KDE Plasma with Klipper enabled (default configuration, integrated into
plasmashell)
Connect a remote desktop client that uses Portal Clipboard (e.g., RDP server
using xdg-desktop-portal API)
Call org.freedesktop.impl.portal.Clipboard.SetSelection via D-Bus with MIME
types
Wait 2-3 seconds for Klipper to monitor and read the clipboard
Observe crash
OBSERVED RESULT
Portal crashes with SIGSEGV in QMimeData::data(). The crash occurs on
KSystemClipboard’s Wayland thread approximately 2 seconds after SetSelection is
called. All clipboard functionality stops working. The crash is 100%
reproducible.
EXPECTED RESULT
Portal continues running, clipboard data is transferred successfully to the
requesting application (Klipper), and clipboard remains functional.
SOFTWARE/OS VERSIONS
Operating System: openSUSE Tumbleweed 20260131 KDE Plasma Version: 6.5.5 KDE
Frameworks Version: 6.22.0 Qt Version: 6.10.1 Kernel Version: 6.18.7-1-default
(64-bit) Graphics Platform: offscreen xdg-desktop-portal-kde: 6.5.5-1.1
BACKTRACE
Stack trace of thread 2450 (Wayland thread - where crash occurs):
#0 0x00007f0ba809dd3c __pthread_kill_implementation (libc.so.6 + 0x9dd3c)
#1 0x00007f0ba80427b6 raise (libc.so.6 + 0x427b6)
#2 0x00007f0bab42f360 _ZN6KCrash19defaultCrashHandlerEi (libKF6Crash.so.6 +
0x8360)
#3 0x00007f0ba8042910 __restore_rt (libc.so.6 + 0x42910)
#4 0x00007f0ba8a1ec95 n/a (libQt6Core.so.6 + 0x21ec95)
#5 0x00007f0ba8a1ee7c n/a (libQt6Core.so.6 + 0x21ee7c)
#6 0x00007f0ba8a1fece _ZNK9QMimeData4dataERK7QString (libQt6Core.so.6 +
0x21fece) ← CRASH HERE
#7 0x00007f0bab929f2c n/a (libKF6GuiAddons.so.6 + 0x40f2c) ←
DataControlSource::ext_data_control_source_v1_send
#8 0x00007f0bab91f468 n/a (libKF6GuiAddons.so.6 + 0x36468) ← DataControlDevice
#9 0x00007f0bab41ec92 n/a (libffi.so.8 + 0x7c92)
#10 0x00007f0bab41ba26 n/a (libffi.so.8 + 0x4a26)
#11 0x00007f0bab41e2ae ffi_call (libffi.so.8 + 0x72ae)
#12 0x00007f0babbd77f3 n/a (libwayland-client.so.0 + 0x77f3)
#13 0x00007f0babbd8539 n/a (libwayland-client.so.0 + 0x8539)
#14 0x00007f0babbd88eb wl_display_dispatch_queue_pending
(libwayland-client.so.0 + 0x88eb)
#15 0x00007f0babbdbdad wl_display_dispatch_queue_timeout
(libwayland-client.so.0 + 0xbdad)
#16 0x00007f0babbdbe7b wl_display_dispatch_queue (libwayland-client.so.0 +
0xbe7b)
#17 0x00007f0bab923626 n/a (libKF6GuiAddons.so.6 + 0x3a626) ←
ClipboardThread::run
#18 0x00007f0ba8b71e68 n/a (libQt6Core.so.6 + 0x371e68)
#19 0x00007f0ba809bdf1 start_thread (libc.so.6 + 0x9bdf1)
#20 0x00007f0ba8120c8c __clone3 (libc.so.6 + 0x120c8c)
ADDITIONAL INFORMATION
Root Cause Analysis
This is a Qt threading violation in the clipboard portal implementation
(src/clipboard.cpp).
The threading violation:
PortalMimeData is created on the main thread (clipboard.cpp:153)
It stores raw pointers to main-thread QObjects:
ClipboardPortal *m_portal (main-thread QObject)
Session *m_session (main-thread QObject)
KSystemClipboard::setMimeData() wraps it in DataControlSource and moves it to
the Wayland thread (waylandclipboard.cpp:652:
source->moveToThread(m_thread.get()))
When Klipper requests clipboard data, the Wayland thread calls
PortalMimeData::retrieveData() (clipboard.cpp:39-46)
This accesses m_portal->fetchData() from the wrong thread, violating Qt’s
threading rules
Result: SIGSEGV in QMimeData::data()
Qt documentation states:
“You must not access a QObject from a thread other than the one that created
it.”
The clipboard portal violates this fundamental Qt threading rule.
Why Klipper Triggers It
Klipper is integrated into plasmashell (not a separate process) and monitors
all clipboard changes via KSystemClipboard::changed signal. When new clipboard
content is announced via Portal SetSelection, Klipper reads the data after
approximately 1-2 seconds (documented Klipper “takeover” behavior).
This read triggers the Wayland compositor to call back into
DataControlSource::ext_data_control_source_v1_send() on the Wayland thread to
actually transfer the data. The callback tries to call mimeData->data() on
PortalMimeData, which then attempts to access main-thread QObjects from the
Wayland thread, causing the crash.
Since Klipper is always active on default KDE Plasma, this bug makes Portal
Clipboard completely unusable.
Impact
Severity: Critical - 100% reproducible crash
Affected users: All remote desktop applications using Portal Clipboard on KDE
Plasma
Examples: RDP servers, VNC servers, screen sharing tools, clipboard sharing
applications
Workaround: None available for end users (requires code fix)
Historical Context
The original clipboard portal implementation (commit 2de83ee0, December 2024)
included a prescient comment from the author:
“If this turns out to be problematic in the future, we can either move
ClipboardPortal into a separate thread and let it do it’s thing there and block
the main thread (for a short time). Or implement the data control protocol
directly.”
The author anticipated threading issues but didn’t realize KSystemClipboard
already uses a separate Wayland thread (added in kguiaddons commit b71af4e to
fix similar threading bugs: BUG 480448, 496029, 502831, 505281, 506467, 507792,
509065, 509689, 511736).
Fix Available
I have developed and tested a fix for this issue. The fix uses
QMetaObject::invokeMethod() with Qt::BlockingQueuedConnection to safely marshal
cross-thread calls back to the main thread, respecting Qt’s threading
requirements while preserving the synchronous API.
The fix changes PortalMimeData::retrieveData() to:
Check if current thread matches portal’s thread
If different, use QMetaObject::invokeMethod() to dispatch to main thread
If same, direct call (fast path)
Change member pointers to QPointer for null-safety
Full technical analysis and patch available in merge request: (will reference
MR number here after submission)
Reproducer
The crash can be reproduced with any application using the Portal Clipboard
API:
Remote desktop servers (RDP, VNC)
Screen sharing applications
Clipboard synchronization tools
Test application: lamco-rdp-server
(https://github.com/gregcman/lamco-rdp-server)
Debug Symbols
Note: Backtrace shown is without debug symbols. For detailed backtrace with
symbols, install:
sudo zypper install xdg-desktop-portal-kde6-debuginfo kf6-kguiaddons-debuginfo
libQt6Core6-debuginfo
However, the crash location is clear from the stack trace:
Thread 2450 (Wayland thread) calling QMimeData::data()
Called from DataControlSource::ext_data_control_source_v1_send() in
libKF6GuiAddons
Which is the Wayland clipboard callback
Source Code Location
File: src/clipboard.cpp Class: PortalMimeData (lines 25-50) Method:
retrieveData() (lines 39-46)
QVariant retrieveData(const QString &mimetype, QMetaType preferredType) const
override
{
Q_UNUSED(preferredType);
if (!m_formats.contains(mimetype)) {
return QVariant();
}
return m_portal->fetchData(m_session, mimetype); // ← UNSAFE CROSS-THREAD
ACCESS
}
This method is called from the Wayland thread but accesses main-thread
QObjects.
--
You are receiving this mail because:
You are watching all bug changes.