| Summary: | Crash (sometimes) in QQmlMetaType::propertyCache when going to a different KCM in Energy Saving > Advanced Power Settings | ||
|---|---|---|---|
| Product: | [Applications] systemsettings | Reporter: | Bharadwaj Raju <bharadwaj.raju777> |
| Component: | kcm_powerdevil | Assignee: | Plasma Bugs List <plasma-bugs-null> |
| Status: | RESOLVED FIXED | ||
| Severity: | crash | CC: | dougshaw77, jpetso, kde, natalie_clarius, nate |
| Priority: | NOR | ||
| Version First Reported In: | master | ||
| Target Milestone: | --- | ||
| Platform: | Other | ||
| OS: | Linux | ||
| Latest Commit: | https://invent.kde.org/frameworks/kcmutils/-/commit/80db4e37396298c5712aa48a943f0a89637f83b7 | Version Fixed/Implemented In: | |
| Sentry Crash Report: | |||
Interestingly the base is 0x0 in lookupScopeObjectProperty, is that normal?
Anyway, from some poking in GDB it appears that the file it happens in is "kcm/kcm_powerdevilprofilesconfig/ComboBoxWithIcon.qml", line 28, which is:
const modelIndex = model.index(currentIndex, 0);
I guess the model is being freed while the page gets unloaded, and sometimes that results in a call to freed memory?
---
(gdb) frame 11
#11 QV4::QQmlContextWrapper::lookupScopeObjectProperty (l=0x1044610, engine=0x87e180, base=0x0)
at /usr/src/debug/qt6-qtdeclarative-6.6.0-1.fc39.x86_64/src/qml/jsruntime/qv4qmlcontext.cpp:637
637 return callWithScopeObject(engine, base, [l, engine, base](const Value &obj) {
(gdb) print engine
$3 = (QV4::ExecutionEngine *) 0x87e180
(gdb) print engine->stackTrace(-1)
$4 = {<QListSpecialMethods<QV4::StackFrame>> = {<QListSpecialMethodsBase<QV4::StackFrame>> = {<No data fields>}, <No data fields>}, d = {d = 0x1a5c620,
ptr = 0x1a5c630, size = 1}}
(gdb) print ((QV4::StackFrame *)(0x1a5c630))->source
$5 = {d = {d = 0x0, ptr = 0x7fffa4032c34 u"qrc:/kcm/kcm_powerdevilprofilesconfig/ComboBoxWithIcon.qml", size = 58}, static _empty = 0 u'\000'}
(gdb) print ((QV4::StackFrame *)(0x1a5c630))->function
$6 = {d = {d = 0x0, ptr = 0x0, size = 0}, static _empty = 0 u'\000'}
(gdb) print ((QV4::StackFrame *)(0x1a5c630))->line
$7 = 28
Cannot reproduce. Operating System: KDE neon Testing Edition KDE Plasma Version: 6.0.0 KDE Frameworks Version: 6.0.0 Qt Version: 6.6.1 Kernel Version: 6.5.0-17-generic (64-bit) Graphics Platform: Wayland Graphics Processor: AMD Radeon Pro WX 3200 Series Can reliably reproduce. It didn't use to crash when I first introduced the new QML-based UI, although it always had QML warnings about underlying stuff being null. Let's see if there's perhaps a signal somewhere that lets me unload the UI before it tries to access unloaded objects. It looks like this kind of stuff should be prevented by the KQuickConfigModule destructor, which seems to unload the QML rootObject: https://invent.kde.org/frameworks/kcmutils/-/blob/master/src/qml/kquickconfigmodule.cpp?ref_type=heads#L71 If my C++ isn't totally off, the destructor order should go like: 1. ~PowerKCM() - no-op 2. ~KQuickManagedConfigModule() - deletes KQuickManagedConfigModulePrivate, which only holds non-owning pointers to KCoreConfigSkeleton objects 3. ~KQuickConfigModule() - unloading QML, see above 4. ~KAbstractConfigModule() - deletes KAbstractConfigModulePrivate, which holds plugin metadata and other only tangentially related stuff 5. ~QObject() - deletes children of PowerKCM, i.e. the various settings and model objects I don't yet see what exactly is going wrong there. What I'm wondering is where the QV4::QQmlContextWrapper::lookupScopeObjectProperty call is coming from in that backtrace, we see a few "???" but I'd be super curious if this happens inside this whole destructor inheritance chain or is called externally somewhere. "Partial" success: If we forcibly delete each subPage of KQuickConfigModule (e.g. by deleting any object returned by takeLast() in ~KQuickConfigModule(), or by parenting a subPage to the already slated-for-deletion d->engine->rootObject()), then page transitions stop crashing while System Settings operates. However, it will crash when trying to close it because apparently QQmlEngine keeps other references to those objects around and they will derefence a freed object on QQmlEngine destruction. Hopefully there's a way to remove these subPage items from the QQmlEngine in some other way that leaves no dangling pointers. (In reply to Jakob Petsovits from comment #5) > "Partial" success: (...). However, it will crash when trying > to close it because apparently QQmlEngine keeps other references to those > objects around and they will derefence a freed object on QQmlEngine > destruction. Looks like that crash (featuring QQuickPopup) is independent from the sub-page crash of this issue, it also occurs when no sub-pages were opened in the first place, or when opening a different KCM than PowerDevil, before and after my reparenting/deletion changes. I'll submit an MR with the "partial" fix and maybe we'll figure out the other crash in a different bug report. A possibly relevant merge request was started @ https://invent.kde.org/frameworks/kcmutils/-/merge_requests/201 Git commit 80db4e37396298c5712aa48a943f0a89637f83b7 by Jakob Petsovits. Committed on 26/02/2024 at 15:57. Pushed by jpetso into branch 'master'. SharedQmlEngine: Don't crash from dangling child item objects In System Settings, navigating away from pushed sub-pages would often crash. The KQuickConfigModule destructor explicitly deletes SharedQmlEngine's rootObject() and implicitly its QQmlContext, but the subPages would stick around. Before this commit, createObjectFromComponent() assigned rootObject() as QObject parent for newly instantiated objects, but not for Qt Quick items. Those would instead have the "parent" property set, i.e. setParentItem(), which does not change the QObject hierarchy. This commit changes the logic to always call QObject::setParent(), and call the optional "parent" property setter in addition to it. This ensures that deleting rootObject() will also get rid of any otherwise dangling sub-pages. M +6 -10 src/qml/sharedqmlengine.cpp https://invent.kde.org/frameworks/kcmutils/-/commit/80db4e37396298c5712aa48a943f0a89637f83b7 |
SUMMARY System Settings sometimes crashes when going to a different KCM from Energy Saving > Advanced Power Settings > Other Settings > Related Pages. STEPS TO REPRODUCE 1. Open the Energy Saving KCM 2. Go to Advanced Power Settings 3. Click, for example, Notifications: Power Management 4. Repeat if necessary BACKTRACE #0 0x00007ffff51a41bf in QQmlMetaType::propertyCache (obj=obj@entry=0x26867a0, version=version@entry=...) at /usr/src/debug/qt6-qtdeclarative-6.6.0-1.fc39.x86_64/src/qml/qml/qqmlmetatype.cpp:1328 #1 0x00007ffff5145582 in QQmlData::createPropertyCache (object=object@entry=0x26867a0) at /usr/include/qt6/QtCore/qversionnumber.h:374 #2 0x00007ffff5059afc in QQmlData::ensurePropertyCache (object=0x26867a0) at /usr/src/debug/qt6-qtdeclarative-6.6.0-1.fc39.x86_64/redhat-linux-build/include/QtQml/6.6.0/QtQml/private/../../../../../../src/qml/qml/qqmldata_p.h:257 #3 QV4::QObjectWrapper::create (engine=<optimized out>, engine@entry=0x87e180, object=object@entry=0x26867a0) at /usr/src/debug/qt6-qtdeclarative-6.6.0-1.fc39.x86_64/src/qml/jsruntime/qv4qobjectwrapper.cpp:796 #4 0x00007ffff5061dd3 in QV4::QObjectWrapper::wrap_slowPath (engine=0x87e180, object=0x26867a0) at /usr/src/debug/qt6-qtdeclarative-6.6.0-1.fc39.x86_64/src/qml/jsruntime/qv4qobjectwrapper.cpp:699 #5 0x00007ffff4fe48fc in QV4::ExecutionEngine::fromData (this=0x87e180, metaType=..., ptr=0x7fffffffa5d0, container=0x7fffbcf2a6e0, property=74, flags=3) at /usr/src/debug/qt6-qtdeclarative-6.6.0-1.fc39.x86_64/src/qml/jsruntime/qv4engine.cpp:1827 #6 0x00007ffff4fe5711 in QV4::ExecutionEngine::fromVariant (this=<optimized out>, variant=<optimized out>, parent=<optimized out>, property=<optimized out>, flags=<optimized out>) at /usr/src/debug/qt6-qtdeclarative-6.6.0-1.fc39.x86_64/src/qml/jsruntime/qv4engine.cpp:1968 #7 0x00007ffff5063035 in QV4::loadProperty (v4=0x87e180, wrapper=0x7fffbcf2a6e0, object=<optimized out>, property=<optimized out>) at /usr/src/debug/qt6-qtdeclarative-6.6.0-1.fc39.x86_64/src/qml/jsruntime/qv4qobjectwrapper.cpp:217 #8 0x00007ffff5056942 in QV4::QObjectWrapper::lookupPropertyGetterImpl<QV4::QQmlContextWrapper::lookupScopeObjectProperty(QV4::Lookup*, QV4::ExecutionEngine*, QV4::Value*)::<lambda(const QV4::Value&)>::<lambda()> > (revertLookup=..., flags=..., object=<optimized out>, engine=0x87e180, lookup=0x1044610) at /usr/src/debug/qt6-qtdeclarative-6.6.0-1.fc39.x86_64/redhat-linux-build/include/QtQml/6.6.0/QtQml/private/../../../../../../src/qml/jsruntime/qv4qobjectwrapper_p.h:299 #9 operator() (obj=<optimized out>, __closure=<synthetic pointer>) at /usr/src/debug/qt6-qtdeclarative-6.6.0-1.fc39.x86_64/src/qml/jsruntime/qv4qmlcontext.cpp:641 #10 callWithScopeObject<QV4::QQmlContextWrapper::lookupScopeObjectProperty(QV4::Lookup*, QV4::ExecutionEngine*, QV4::Value*)::<lambda(const QV4::Value&)> > (c=..., base=0x0, engine=0x87e180) at /usr/src/debug/qt6-qtdeclarative-6.6.0-1.fc39.x86_64/src/qml/jsruntime/qv4qmlcontext.cpp:632 #11 QV4::QQmlContextWrapper::lookupScopeObjectProperty (l=0x1044610, engine=0x87e180, base=0x0) at /usr/src/debug/qt6-qtdeclarative-6.6.0-1.fc39.x86_64/src/qml/jsruntime/qv4qmlcontext.cpp:637 #12 0x00007fff895d8701 in ??? () #13 0x0000000000000000 in ??? ()