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 ()
> KIconLoader::~KIconLoader() That's weird, I wonder why we're in KIconLoader at all.
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 :)
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
``` ~ $ 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?
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
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==
Created attachment 160372 [details] kwayland patch to support foreing connection by reister Do not break foreign wayland connection during registry destroy.
Created attachment 160373 [details] kscreen use kwayland registry with foreign support
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.
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?
(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