Bug 469160 - kscreen-doctor segmentation faults in KIconLoader::~KIconLoader() when exiting
Summary: kscreen-doctor segmentation faults in KIconLoader::~KIconLoader() when exiting
Status: CONFIRMED
Alias: None
Product: KScreen
Classification: Plasma
Component: kscreen-doctor (show other bugs)
Version: 5.27.4
Platform: Arch Linux Linux
: NOR crash
Target Milestone: ---
Assignee: kscreen-bugs-null@kde.org
URL:
Keywords: wayland
Depends on:
Blocks:
 
Reported: 2023-04-29 21:44 UTC by mooodyhunter@outlook.com
Modified: 2024-05-05 20:41 UTC (History)
5 users (show)

See Also:
Latest Commit:
Version Fixed In:
Sentry Crash Report:


Attachments
kwayland patch to support foreing connection by reister (1.49 KB, patch)
2023-07-18 23:40 UTC, Misha Labjuk
Details
kscreen use kwayland registry with foreign support (490 bytes, patch)
2023-07-18 23:42 UTC, Misha Labjuk
Details

Note You need to log in before you can comment on or make changes to this bug.
Description mooodyhunter@outlook.com 2023-04-29 21:44:02 UTC
SUMMARY
kscreen-doctor sometimes gets killed (when calling the destructors?)

STEPS TO REPRODUCE
1. run `kscreen-doctor -j`
2. sometimes it aborts with "malloc_consolidate(): unaligned fastbin chunk detected"

OBSERVED RESULT

Sometimes:

~ > kscreen-doctor -j
malloc_consolidate(): unaligned fastbin chunk detected
fish: Job 1, 'kscreen-doctor -j' terminated by signal SIGABRT (Abort)


EXPECTED RESULT
kscreen-doctor prints my screen config normally

SOFTWARE/OS VERSIONS
Linux/KDE Plasma: /usr/bin/kscreen-doctor is owned by libkscreen 5.27.4-1
(available in About System)
KDE Plasma Version: 5.27.4
KDE Frameworks Version: 5.105.0
Qt Version: 5.15.9

ADDITIONAL INFORMATION

Thread 1 "kscreen-doctor" received signal SIGABRT, Aborted.
__pthread_kill_implementation (threadid=<optimized out>, signo=signo@entry=6, no_tid=no_tid@entry=0) at pthread_kill.c:44
44            return INTERNAL_SYSCALL_ERROR_P (ret) ? INTERNAL_SYSCALL_ERRNO (ret) : 0;                                                                                                                    
(gdb) bt
#0  __pthread_kill_implementation (threadid=<optimized out>, signo=signo@entry=6, no_tid=no_tid@entry=0) at pthread_kill.c:44
#1  0x00007ffff6ca0953 in __pthread_kill_internal (signo=6, threadid=<optimized out>) at pthread_kill.c:78
#2  0x00007ffff6c51ea8 in __GI_raise (sig=sig@entry=6) at ../sysdeps/posix/raise.c:26
#3  0x00007ffff6c3b53d in __GI_abort () at abort.c:79
#4  0x00007ffff6c3c29e in __libc_message (fmt=fmt@entry=0x7ffff6db377e "%s\n") at ../sysdeps/posix/libc_fatal.c:150
#5  0x00007ffff6caa657 in malloc_printerr (str=str@entry=0x7ffff6db6400 "malloc_consolidate(): unaligned fastbin chunk detected") at malloc.c:5651
#6  0x00007ffff6cab2ec in malloc_consolidate (av=av@entry=0x7ffff6df1aa0 <main_arena>) at malloc.c:4736
#7  0x00007ffff6cac7e0 in _int_free (av=0x7ffff6df1aa0 <main_arena>, p=0x555555813ad0, have_lock=<optimized out>, have_lock@entry=0) at malloc.c:4660
#8  0x00007ffff6caee63 in __GI___libc_free (mem=<optimized out>) at malloc.c:3367
#9  0x00007ffff72ea9b6 in QArrayData::deallocate (data=<optimized out>, objectSize=objectSize@entry=2, alignment=alignment@entry=8) at tools/qarraydata.cpp:267
#10 0x00007ffff1e7b844 in QTypedArrayData<unsigned short>::deallocate (data=<optimized out>) at /usr/include/qt/QtCore/qarraydata.h:237
#11 QString::~QString (this=<optimized out>, this=<optimized out>) at /usr/include/qt/QtCore/qstring.h:1311
#12 QString::~QString (this=<optimized out>, this=<optimized out>) at /usr/include/qt/QtCore/qstring.h:1311
#13 KIconThemeDir::~KIconThemeDir (this=<optimized out>, this=<optimized out>) at /usr/src/debug/kiconthemes/kiconthemes-5.105.0/src/kicontheme.cpp:114
#14 qDeleteAll<QTypedArrayData<KIconThemeDir*>::const_iterator> (end=..., begin=...) at /usr/include/qt/QtCore/qalgorithms.h:320
#15 qDeleteAll<QVector<KIconThemeDir*> > (c=...) at /usr/include/qt/QtCore/qalgorithms.h:328
#16 KIconTheme::~KIconTheme (this=<optimized out>, this=<optimized out>) at /usr/src/debug/kiconthemes/kiconthemes-5.105.0/src/kicontheme.cpp:391
#17 0x00007ffff1e74a9a in KIconThemeNode::~KIconThemeNode (this=<optimized out>, this=<optimized out>) at /usr/src/debug/kiconthemes/kiconthemes-5.105.0/src/kiconloader.cpp:127
#18 qDeleteAll<QList<KIconThemeNode*>::const_iterator> (end=..., begin=...) at /usr/include/qt/QtCore/qalgorithms.h:320
#19 qDeleteAll<QList<KIconThemeNode*> > (c=...) at /usr/include/qt/QtCore/qalgorithms.h:328
#20 KIconLoaderPrivate::clear (this=this@entry=0x5555557a79c0) at /usr/src/debug/kiconthemes/kiconthemes-5.105.0/src/kiconloader.cpp:255
#21 0x00007ffff1e76fde in KIconLoaderPrivate::~KIconLoaderPrivate (this=<optimized out>, this=<optimized out>) at /usr/src/debug/kiconthemes/kiconthemes-5.105.0/src/kiconloader.cpp:243
#22 std::default_delete<KIconLoaderPrivate>::operator() (this=<optimized out>, __ptr=0x5555557a79c0) at /usr/include/c++/12.2.1/bits/unique_ptr.h:95
#23 std::default_delete<KIconLoaderPrivate>::operator() (__ptr=0x5555557a79c0, this=<optimized out>) at /usr/include/c++/12.2.1/bits/unique_ptr.h:89
#24 std::unique_ptr<KIconLoaderPrivate, std::default_delete<KIconLoaderPrivate> >::~unique_ptr (this=<optimized out>, this=<optimized out>) at /usr/include/c++/12.2.1/bits/unique_ptr.h:396
#25 KIconLoader::~KIconLoader (this=<optimized out>, this=<optimized out>) at /usr/src/debug/kiconthemes/kiconthemes-5.105.0/src/kiconloader.cpp:460
#26 0x00007ffff1e771ee in (anonymous namespace)::Q_QGS_globalIconLoader::innerFunction()::Holder::~Holder() () at /usr/src/debug/kiconthemes/kiconthemes-5.105.0/src/kiconloader.cpp:1656
#27 0x00007ffff6c54445 in __run_exit_handlers (status=0, listp=0x7ffff6df1660 <__exit_funcs>, run_list_atexit=run_list_atexit@entry=true, run_dtors=run_dtors@entry=true) at exit.c:108
#28 0x00007ffff6c545b0 in __GI_exit (status=<optimized out>) at exit.c:138
#29 0x00007ffff6c3c797 in __libc_start_call_main (main=main@entry=0x555555559170 <main(int, char**)>, argc=argc@entry=2, argv=argv@entry=0x7fffffffe208) at ../sysdeps/nptl/libc_start_call_main.h:74
#30 0x00007ffff6c3c84a in __libc_start_main_impl (main=0x555555559170 <main(int, char**)>, argc=2, argv=0x7fffffffe208, init=<optimized out>, fini=<optimized out>, rtld_fini=<optimized out>, 
    stack_end=0x7fffffffe1f8) at ../csu/libc-start.c:360
#31 0x000055555555aa15 in _start ()
Comment 1 Nate Graham 2023-05-02 16:28:18 UTC
> KIconLoader::~KIconLoader()

That's weird, I wonder why we're in KIconLoader at all.
Comment 2 mooodyhunter@outlook.com 2023-05-03 01:06:52 UTC
This looks strange to me as well, after digging into the problem, it seems to be:

- We are using `QGuiApplication`, so that Qt's platform theme is loaded (in my case it's `/usr/lib/qt/plugins/platformthemes/KDEPlasmaPlatformTheme.so`)
- `KDEPlasmaPlatformTheme` depends on `libKF5IconThemes.so.5` so that the latter is loaded
- As can be seen in the backtrace, there is a QGlobalStatic instance, (this one: https://github.com/KDE/kiconthemes/blob/v5.105.0/src/kiconloader.cpp#L1656)

It seems to be something with its destructor, a minimal reproducible is attached below

```
#include <KScreen/GetConfigOperation>
#include <QGuiApplication>
#include <iostream>

int main(int argc, char **argv)
{
    QGuiApplication app(argc, argv);
    KScreen::GetConfigOperation *op = new KScreen::GetConfigOperation();
    QObject::connect(op, &KScreen::GetConfigOperation::finished,
                     [&](KScreen::ConfigOperation *)
                     {
                         std::cout << "Leaving app" << std::endl; // "Leaving app
                         qApp->exit();
                     });
    return app.exec();
}
```

Compile with `g++ ./test.cpp -I /usr/include/KF5/KScreen/ -I /usr/include/qt/ -I /usr/include/qt/QtCore/ -I /usr/include/qt/QtGui/ -lQt5Core -lQt5Gui -lKF5Screen` and run several times.


** One thing to note that, it seems the problem doesn't occur (at all) on my friends' computers. **

Would be great if anyone can point out possible causes :)
Comment 3 Ryan Rix 2023-06-01 22:50:46 UTC
This only happens when I am running kwin_wayland -- kwin_x11 does not exhibit this issue. 

in my case it's slightly different behavior but only occurs on kwin_wayland:

```
~ $ kscreen-doctor --json 
warning: queue 0x1aec2f0 destroyed while proxies still attached:
  wl_display@1 still attached
corrupted size vs. prev_size in fastbins
aborted (core dumped)
```

Thread 1 (Thread 0x7ffff3cff880 (LWP 3617698) ".kscreen-doctor"):
#0  0x00007ffff6e21adc in __pthread_kill_implementation () from /nix/store/yaz7pyf0ah88g2v505l38n0f3wg2vzdj-glibc-2.37-8/lib/libc.so.6
#1  0x00007ffff6dd2cb6 in raise () from /nix/store/yaz7pyf0ah88g2v505l38n0f3wg2vzdj-glibc-2.37-8/lib/libc.so.6
#2  0x00007ffff6dbc8ba in abort () from /nix/store/yaz7pyf0ah88g2v505l38n0f3wg2vzdj-glibc-2.37-8/lib/libc.so.6
#3  0x00007ffff6dbd5f5 in __libc_message.cold () from /nix/store/yaz7pyf0ah88g2v505l38n0f3wg2vzdj-glibc-2.37-8/lib/libc.so.6
#4  0x00007ffff6e2b785 in malloc_printerr () from /nix/store/yaz7pyf0ah88g2v505l38n0f3wg2vzdj-glibc-2.37-8/lib/libc.so.6
#5  0x00007ffff6e2c04e in unlink_chunk.constprop () from /nix/store/yaz7pyf0ah88g2v505l38n0f3wg2vzdj-glibc-2.37-8/lib/libc.so.6
#6  0x00007ffff6e2d6cb in _int_free () from /nix/store/yaz7pyf0ah88g2v505l38n0f3wg2vzdj-glibc-2.37-8/lib/libc.so.6
#7  0x00007ffff6e2fe83 in free () from /nix/store/yaz7pyf0ah88g2v505l38n0f3wg2vzdj-glibc-2.37-8/lib/libc.so.6
#8  0x00007fffe4a2a3c3 in KIconTheme::~KIconTheme() () from /nix/store/d57as4xqqimmrisfn48nwx81hh7851ck-kiconthemes-5.106.0/lib/libKF5IconThemes.so.5
#9  0x00007fffe4a22e7a in KIconLoaderPrivate::clear() () from /nix/store/d57as4xqqimmrisfn48nwx81hh7851ck-kiconthemes-5.106.0/lib/libKF5IconThemes.so.5
#10 0x00007fffe4a2312e in KIconLoaderPrivate::~KIconLoaderPrivate() () from /nix/store/d57as4xqqimmrisfn48nwx81hh7851ck-kiconthemes-5.106.0/lib/libKF5IconThemes.so.5
#11 0x00007fffe4a23398 in KIconLoader::~KIconLoader() () from /nix/store/d57as4xqqimmrisfn48nwx81hh7851ck-kiconthemes-5.106.0/lib/libKF5IconThemes.so.5
#12 0x00007fffe4a233e9 in (anonymous namespace)::Q_QGS_globalIconLoader::innerFunction()::Holder::~Holder() () from /nix/store/d57as4xqqimmrisfn48nwx81hh7851ck-kiconthemes-5.106.0/lib/libKF5IconThemes.so.5
#13 0x00007ffff6dd5285 in __run_exit_handlers () from /nix/store/yaz7pyf0ah88g2v505l38n0f3wg2vzdj-glibc-2.37-8/lib/libc.so.6
#14 0x00007ffff6dd53be in exit () from /nix/store/yaz7pyf0ah88g2v505l38n0f3wg2vzdj-glibc-2.37-8/lib/libc.so.6
#15 0x00007ffff6dbdad5 in __libc_start_call_main () from /nix/store/yaz7pyf0ah88g2v505l38n0f3wg2vzdj-glibc-2.37-8/lib/libc.so.6
#16 0x00007ffff6dbdb89 in __libc_start_main_impl () from /nix/store/yaz7pyf0ah88g2v505l38n0f3wg2vzdj-glibc-2.37-8/lib/libc.so.6
#17 0x0000000000406165 in _start ()

Operating System: NixOS 23.11
KDE Plasma Version: 5.27.5
KDE Frameworks Version: 5.106.0
Qt Version: 5.15.9
Kernel Version: 6.1.30 (64-bit)
Graphics Platform: Wayland
Processors: 8 × Intel® Core™ i7-7700K CPU @ 4.20GHz
Memory: 62.7 GiB of RAM
Graphics Processor: Mesa Intel® HD Graphics 630
Comment 4 Ryan Rix 2023-06-03 20:21:54 UTC
```
~ $ KSCREEN_BACKEND=QScreen kscreen-doctor --json | jq .outputs[0].name
kscreen.qscreen: Screen added QScreen(0x12e4010, name="DSI-1") "DSI-1"
warning: queue 0x12f48e0 destroyed while proxies still attached:
  wl_display@1 still attached
"DSI-1"
~ $ KSCREEN_BACKEND=KWayland kscreen-doctor --json | jq .outputs[0].name
warning: queue 0x1bc6880 destroyed while proxies still attached:
  wl_display@1 still attached
corrupted double-linked list
parse error: Invalid numeric literal at line 1, column 8
```

seems like the issue is specific to the KWayland backend, i feel like our backtraces are maybe a red herring?
Comment 5 mooodyhunter@outlook.com 2023-06-03 21:12:07 UTC
Tested with `KSCREEN_BACKEND=KWayland` vs QScreen... and yes the problem has never occurred with QScreen backend.

> i feel like our backtraces are maybe a red herring?

Yes so do I
Comment 6 Misha Labjuk 2023-07-16 23:23:35 UTC
Valgrind show this error:

==508424== Invalid write of size 8
==508424==    at 0x5A42327: wl_list_remove (in /usr/lib64/libwayland-client.so.0.22.0)
==508424==    by 0x5A3DD7D: ??? (in /usr/lib64/libwayland-client.so.0.22.0)
==508424==    by 0x5A3E1E3: wl_proxy_marshal_array_flags (in /usr/lib64/libwayland-client.so.0.22.0)
==508424==    by 0x5A3E404: wl_proxy_marshal_flags (in /usr/lib64/libwayland-client.so.0.22.0)
==508424==    by 0x5AB587E: wl_touch_release (wayland-wayland-client-protocol.h:4994)
==508424==    by 0x5AB8C5A: QtWaylandClient::QWaylandInputDevice::Touch::~Touch() (qwaylandinputdevice.cpp:397)
==508424==    by 0x5AB8C8A: QtWaylandClient::QWaylandInputDevice::Touch::~Touch() (qwaylandinputdevice.cpp:400)
==508424==    by 0x5AB8BD0: QtWaylandClient::QWaylandInputDevice::~QWaylandInputDevice() (qwaylandinputdevice.cpp:433)
==508424==    by 0x5AB8C20: QtWaylandClient::QWaylandInputDevice::~QWaylandInputDevice() (qwaylandinputdevice.cpp:434)
==508424==    by 0x5ABF614: void qDeleteAll<QList<QtWaylandClient::QWaylandInputDevice*>::const_iterator>(QList<QtWaylandClient::QWaylandInputDevice*>::const_iterator, QList<QtWaylandClient::QWaylandInputDevice*>::const_iterator) (qalgorithms.h:320)
==508424==    by 0x5ABF67C: void qDeleteAll<QList<QtWaylandClient::QWaylandInputDevice*> >(QList<QtWaylandClient::QWaylandInputDevice*> const&) (qalgorithms.h:328)
==508424==    by 0x5ABE30C: QtWaylandClient::QWaylandDisplay::~QWaylandDisplay() (qwaylanddisplay.cpp:369)


==508424==  Address 0x20219b98 is 88 bytes inside a block of size 96 free'd
==508424==    at 0x484300B: free (vg_replace_malloc.c:974)
==508424==    by 0x2056BF6B: KWayland::Client::WaylandPointer<wl_registry, &wl_registry_destroy>::destroy() (wayland_pointer_p.h:55)
==508424==    by 0x2056BFA3: KWayland::Client::Registry::destroy() (registry.cpp:465)
==508424==    by 0x2057648F: QtPrivate::FunctorCall<QtPrivate::IndexesList<>, QtPrivate::List<>, void, void (KWayland::Client::Registry::*)()>::call(void (KWayland::Client::Registry::*)(), KWayland::Client::Registry*, void**) (qobjectdefs_impl.h:152)
==508424==    by 0x205764D1: call<QtPrivate::List<>, void> (qobjectdefs_impl.h:185)
==508424==    by 0x205764D1: QtPrivate::QSlotObject<void (KWayland::Client::Registry::*)(), QtPrivate::List<>, void>::impl(int, QtPrivate::QSlotObjectBase*, QObject*, void**, bool*) (qobjectdefs_impl.h:418)
==508424==    by 0x5159D14: ??? (in /usr/lib64/libQt5Core.so.5.15.10)
==508424==    by 0x20545DAB: KWayland::Client::ConnectionThread::connectionDied() (moc_connection_thread.cpp:212)
==508424==    by 0x20555CD9: QtPrivate::FunctorCall<QtPrivate::IndexesList<>, QtPrivate::List<>, void, void (KWayland::Client::ConnectionThread::*)()>::call(void (KWayland::Client::ConnectionThread::*)(), KWayland::Client::ConnectionThread*, void**) (qobjectdefs_impl.h:152)
==508424==    by 0x20555D1B: call<QtPrivate::List<>, void> (qobjectdefs_impl.h:185)
==508424==    by 0x20555D1B: QtPrivate::QSlotObject<void (KWayland::Client::ConnectionThread::*)(), QtPrivate::List<>, void>::impl(int, QtPrivate::QSlotObjectBase*, QObject*, void**, bool*) (qobjectdefs_impl.h:418)
==508424==    by 0x5159D14: ??? (in /usr/lib64/libQt5Core.so.5.15.10)
==508424==    by 0x5154F2E: QObject::destroyed(QObject*) (in /usr/lib64/libQt5Core.so.5.15.10)
==508424==    by 0x5156BFA: QObject::~QObject() (in /usr/lib64/libQt5Core.so.5.15.10)


==508424==  Block was alloc'd at
==508424==    at 0x48456FF: calloc (vg_replace_malloc.c:1554)
==508424==    by 0x5A3D623: ??? (in /usr/lib64/libwayland-client.so.0.22.0)
==508424==    by 0x5A3E10D: wl_proxy_marshal_array_flags (in /usr/lib64/libwayland-client.so.0.22.0)
==508424==    by 0x5A3E404: wl_proxy_marshal_flags (in /usr/lib64/libwayland-client.so.0.22.0)
==508424==    by 0x2056BFE2: wl_display_get_registry (wayland-client-protocol.h:1074)
==508424==    by 0x2056C245: KWayland::Client::Registry::create(wl_display*) (registry.cpp:473)
==508424==    by 0x2056DCDE: KWayland::Client::Registry::create(KWayland::Client::ConnectionThread*) (registry.cpp:483)
==508424==    by 0x204A9AFF: KScreen::WaylandConfig::setupRegistry() (waylandconfig.cpp:151)
==508424==    by 0x204A9B3E: KScreen::WaylandConfig::initConnection() (waylandconfig.cpp:99)
==508424==    by 0x204A9F80: KScreen::WaylandConfig::WaylandConfig(QObject*) (waylandconfig.cpp:54)
==508424==    by 0x204A835B: KScreen::WaylandBackend::WaylandBackend() (waylandbackend.cpp:31)
==508424==    by 0x204A7087: qt_plugin_instance (moc_waylandbackend.cpp:114)
==508424==
Comment 7 Misha Labjuk 2023-07-18 23:40:27 UTC
Created attachment 160372 [details]
kwayland patch to support foreing connection by reister

Do not break foreign wayland connection during registry destroy.
Comment 8 Misha Labjuk 2023-07-18 23:42:28 UTC
Created attachment 160373 [details]
kscreen use kwayland registry with foreign support
Comment 9 Misha Labjuk 2023-07-18 23:48:23 UTC
This two patches works for me.

Main reason for this issue is kwayland cleanup called by  QCoreApplication::quit() signal free registry structure.
Registry is a wayland proxy object and it can't be freed before detach.

Other wayland users like qtwayland  try to access this memory after free.
Comment 10 Nate Graham 2023-07-19 03:04:19 UTC
Thanks for the patches, Misha! Can you submit them at https://invent.kde.org/frameworks/kwayland/-/merge_requests and https://invent.kde.org/plasma/kscreen/-/merge_requests so they get seen by developers?
Comment 11 Misha Labjuk 2023-07-23 06:17:51 UTC
(In reply to Nate Graham from comment #10)
> Thanks for the patches, Misha! Can you submit them at https://invent.kde.org/frameworks/kwayland/-/merge_requests  so they get seen by
> developers?

Done. https://invent.kde.org/frameworks/kwayland/-/merge_requests/100