Bug 435532

Summary: Crash in KSysGuard::Process::userUsage() while browsing processes page
Product: [Applications] plasma-systemmonitor Reporter: Nate Graham <nate>
Component: generalAssignee: KSysGuard Developers <ksysguard-bugs>
Status: RESOLVED FIXED    
Severity: crash CC: ahiemstra, kde, plasma-bugs-null
Priority: NOR    
Version First Reported In: unspecified   
Target Milestone: ---   
Platform: Other   
OS: Linux   
Latest Commit: Version Fixed/Implemented In:
Sentry Crash Report:

Description Nate Graham 2021-04-09 05:00:38 UTC
Everything KDE from git master on openSUSE Tumbleweed.

I have seen this crash twice, though I cannot reproduce it on demand.


Core was generated by `plasma-systemmonitor'.
Program terminated with signal SIGSEGV, Segmentation fault.
#0  0x00007fb034251984 in KSysGuard::Process::userUsage (this=this@entry=0x36e5e30)
    at /home/nate/kde/src/libksysguard/processcore/process.cpp:308
308         return d->userUsage;
[Current thread is 1 (Thread 0x7fb05985d880 (LWP 18644))]
(gdb) bt
#0  0x00007fb034251984 in KSysGuard::Process::userUsage (this=this@entry=0x36e5e30)
    at /home/nate/kde/src/libksysguard/processcore/process.cpp:308
#1  0x00007fb034248ec1 in operator() (__closure=<optimized out>, p=0x36e5e30)
    at /home/nate/kde/src/libksysguard/processcore/extended_process_list.cpp:214
#2  std::__invoke_impl<int, KSysGuard::ExtendedProcesses::ExtendedProcesses(QObject*)::<lambda(KSysGuard::Process*)>&, KSysGuard::Process*> (__f=...) at /usr/include/c++/10/bits/invoke.h:60
#3  std::__invoke_r<int, KSysGuard::ExtendedProcesses::ExtendedProcesses(QObject*)::<lambda(KSysGuard::Process*)>&, KSysGuard::Process*> (__fn=...) at /usr/include/c++/10/bits/invoke.h:113
#4  std::_Function_handler<int(KSysGuard::Process*), KSysGuard::ExtendedProcesses::ExtendedProcesses(QObject*)::<lambda(KSysGuard::Process*)> >::_M_invoke(const std::_Any_data &, KSysGuard::Process *&&) (__functor=..., __args#0=<optimized out>) at /usr/include/c++/10/bits/std_function.h:291
#5  0x00007fb03424d0c9 in std::function<int (KSysGuard::Process*)>::operator()(KSysGuard::Process*) const (__args#0=<optimized out>, this=<optimized out>)
    at /usr/include/c++/10/bits/std_function.h:622
#6  ProcessSensor<int>::data (this=<optimized out>, process=<optimized out>)
    at /home/nate/kde/src/libksysguard/processcore/extended_process_list.cpp:74
#7  0x00007fb0342527ab in operator() (process=<optimized out>, total=32, 
    __closure=<synthetic pointer>)
    at /home/nate/kde/src/libksysguard/processcore/process_attribute.cpp:169
#8  std::accumulate<KSysGuard::Process* const*, double, KSysGuard::ProcessAttribute::cgroupData(KSysGuard::CGroup*, const QVector<KSysGuard::Process*>&) const::<lambda(qreal, KSysGuard::Process*)> >
    (__binary_op=..., __init=32, __last=0x35ce5b0, __first=0x35ce568)
    at /usr/include/c++/10/bits/stl_numeric.h:169
#9  KSysGuard::ProcessAttribute::cgroupData (this=this@entry=0x4b50960, 
    cgroup=cgroup@entry=0x4fa3e50, groupProcesses=...)
    at /home/nate/kde/src/libksysguard/processcore/process_attribute.cpp:168
#10 0x00007fb0342477ca in KSysGuard::CGroupDataModel::data (this=0x4b430a0, index=..., 
    role=<optimized out>) at /home/nate/kde/src/libksysguard/processcore/cgroup_data_model.cpp:258
#11 0x00007fb05bc1494e in QAbstractProxyModel::data (this=<optimized out>, proxyIndex=..., 
    role=256) at itemmodels/qabstractproxymodel.cpp:245
#12 0x00007fb03421c68d in ColumnDisplayModel::data (this=0x4b42d30, index=..., 
    role=<optimized out>)
    at /home/nate/kde/src/plasma-systemmonitor/src/table/ColumnDisplayModel.cpp:36
#13 0x00007fb05bc1494e in QAbstractProxyModel::data (this=<optimized out>, proxyIndex=..., 
    role=256) at itemmodels/qabstractproxymodel.cpp:245
#14 0x00007fb03421ebd4 in ComponentCacheProxyModel::data (this=0x4b42850, proxyIndex=..., 
    role=<optimized out>)
    at /home/nate/kde/src/plasma-systemmonitor/src/table/ComponentCacheProxyModel.cpp:48
#15 0x00007fb05bc23749 in QSortFilterProxyModel::data (this=<optimized out>, index=..., role=256)
    at itemmodels/qsortfilterproxymodel.cpp:2250
#16 0x00007fb05c62ff4f in QModelIndex::data (arole=256, this=0x7ffd816957c0)
    at /usr/include/qt5/QtCore/qabstractitemmodel.h:460
#17 QQmlDMAbstractItemModelData::value (role=256, this=0x4f42580)
    at /usr/src/debug/libqt5-qtdeclarative-5.15.2-3.1.x86_64/src/qmlmodels/qqmladaptormodel.cpp:414
#18 QQmlDMCachedModelData::metaCall (this=0x4f42580, call=<optimized out>, id=<optimized out>, 
    arguments=0x7ffd81695870)
    at /usr/src/debug/libqt5-qtdeclarative-5.15.2-3.1.x86_64/src/qmlmodels/qqmladaptormodel.cpp:282
#19 0x00007fb05c3247c1 in QQmlPropertyData::readPropertyWithArgs (this=<optimized out>, 
    this=<optimized out>, args=0x7ffd81695870, target=0x4f42580)
    at /usr/src/debug/libqt5-qtdeclarative-5.15.2-3.1.x86_64/include/QtQml/5.15.2/QtQml/private/../.--Type <RET> for more, q to quit, c to continue without paging--
./../../../src/qml/qml/qqmlpropertydata_p.h:285
#20 QQmlPropertyData::readPropertyWithArgs (args=0x7ffd81695870, target=0x4f42580, this=0x4de7008)
    at /usr/src/debug/libqt5-qtdeclarative-5.15.2-3.1.x86_64/include/QtQml/5.15.2/QtQml/private/../../../../../src/qml/qml/qqmlpropertydata_p.h:360
#21 QQmlPropertyData::readProperty (property=0x7ffd81695850, target=0x4f42580, this=0x4de7008)
    at /usr/src/debug/libqt5-qtdeclarative-5.15.2-3.1.x86_64/include/QtQml/5.15.2/QtQml/private/../../../../../src/qml/qml/qqmlpropertydata_p.h:357
#22 loadProperty (v4=0x7fb050006fe0, object=0x4f42580, property=...)
    at /usr/src/debug/libqt5-qtdeclarative-5.15.2-3.1.x86_64/src/qml/jsruntime/qv4qobjectwrapper.cpp:176
#23 0x00007fb0340aa8ba in ?? ()
#24 0x0000000000000000 in ?? ()
Comment 1 David Edmundson 2021-04-09 09:09:36 UTC
valggrind log

I suspect it's a regression with the shared processes's list 

,QObject(0x0)) is not valid (expected valid)
==60008== Invalid read of size 8
==60008==    at 0x1BA3B27C: KSysGuard::Process::userUsage() const (src/kde/workspace/libksysguard/processcore/process.cpp:308)
==60008==    by 0x1BA29F48: KSysGuard::ExtendedProcesses::ExtendedProcesses(QObject*)::$_25::operator()(KSysGuard::Process*) const (src/kde/workspace/libksysguard/processcore/extended_process_list.cpp:214)
==60008==    by 0x1BA29F11: int std::__invoke_impl<int, KSysGuard::ExtendedProcesses::ExtendedProcesses(QObject*)::$_25&, KSysGuard::Process*>(std::__invoke_other, KSysGuard::ExtendedProcesses::ExtendedProcesses(QObject*)::$_25&, KSysGuard::Process*&&) (invoke.h:60)
==60008==    by 0x1BA29EA1: std::enable_if<is_invocable_r_v<int, KSysGuard::ExtendedProcesses::ExtendedProcesses(QObject*)::$_25&, KSysGuard::Process*>, int>::type std::__invoke_r<int, KSysGuard::ExtendedProcesses::ExtendedProcesses(QObject*)::$_25&, KSysGuard::Process*>(KSysGuard::ExtendedProcesses::ExtendedProcesses(QObject*)::$_25&, KSysGuard::Process*&&) (invoke.h:113)
==60008==    by 0x1BA29DA1: std::_Function_handler<int (KSysGuard::Process*), KSysGuard::ExtendedProcesses::ExtendedProcesses(QObject*)::$_25>::_M_invoke(std::_Any_data const&, KSysGuard::Process*&&) (std_function.h:291)
==60008==    by 0x1BA30CB3: std::function<int (KSysGuard::Process*)>::operator()(KSysGuard::Process*) const (std_function.h:622)
==60008==    by 0x1BA3091F: ProcessSensor<int>::data(KSysGuard::Process*) const (src/kde/workspace/libksysguard/processcore/extended_process_list.cpp:74)
==60008==    by 0x1BA3DA0D: KSysGuard::ProcessAttribute::cgroupData(KSysGuard::CGroup*, QVector<KSysGuard::Process*> const&) const::$_0::operator()(double, KSysGuard::Process*) const (src/kde/workspace/libksysguard/processcore/process_attribute.cpp:169)
==60008==    by 0x1BA3D788: double std::accumulate<KSysGuard::Process* const*, double, KSysGuard::ProcessAttribute::cgroupData(KSysGuard::CGroup*, QVector<KSysGuard::Process*> const&) const::$_0>(KSysGuard::Process* const*, KSysGuard::Process* const*, double, KSysGuard::ProcessAttribute::cgroupData(KSysGuard::CGroup*, QVector<KSysGuard::Process*> const&) const::$_0) (stl_numeric.h:169)
==60008==    by 0x1BA3D715: KSysGuard::ProcessAttribute::cgroupData(KSysGuard::CGroup*, QVector<KSysGuard::Process*> const&) const (src/kde/workspace/libksysguard/processcore/process_attribute.cpp:168)
==60008==    by 0x1BA15EA0: KSysGuard::CGroupDataModel::data(QModelIndex const&, int) const (src/kde/workspace/libksysguard/processcore/cgroup_data_model.cpp:258)
==60008==    by 0x78EF8D3: QAbstractProxyModel::data(QModelIndex const&, int) const (qabstractproxymodel.cpp:245)
==60008==  Address 0x17070bf8 is 8 bytes inside a block of size 16 free'd
==60008==    at 0x483FEAB: operator delete(void*) (vg_replace_malloc.c:584)
==60008==    by 0x1BA3A9A7: KSysGuard::Process::~Process() (src/kde/workspace/libksysguard/processcore/process.cpp:108)
==60008==    by 0x1BA36EE7: KSysGuard::Processes::deleteProcess(long) (src/kde/workspace/libksysguard/processcore/processes.cpp:430)
==60008==    by 0x1BA341AD: KSysGuard::Processes::processesUpdated() (src/kde/workspace/libksysguard/processcore/processes.cpp:330)
==60008==    by 0x1BA38D50: QtPrivate::FunctorCall<QtPrivate::IndexesList<>, QtPrivate::List<>, void, void (KSysGuard::Processes::*)()>::call(void (KSysGuard::Processes::*)(), KSysGuard::Processes*, void**) (qobjectdefs_impl.h:152)
==60008==    by 0x1BA38CB7: void QtPrivate::FunctionPointer<void (KSysGuard::Processes::*)()>::call<QtPrivate::List<>, void>(void (KSysGuard::Processes::*)(), KSysGuard::Processes*, void**) (qobjectdefs_impl.h:185)
==60008==    by 0x1BA38BE4: QtPrivate::QSlotObject<void (KSysGuard::Processes::*)(), QtPrivate::List<>, void>::impl(int, QtPrivate::QSlotObjectBase*, QObject*, void**, bool*) (qobjectdefs_impl.h:418)
==60008==    by 0x794AC56: QtPrivate::QSlotObjectBase::call(QObject*, void**) (qobjectdefs_impl.h:398)
==60008==    by 0x798DF0F: void doActivate<false>(QObject*, int, void**) (qobject.cpp:3886)
==60008==    by 0x7987470: QMetaObject::activate(QObject*, QMetaObject const*, int, void**) (qobject.cpp:3946)
==60008==    by 0x1BA0B374: KSysGuard::AbstractProcesses::processesUpdated() (moc_processes_base_p.cpp:157)
==60008==    by 0x1BA4197D: KSysGuard::ProcessesLocal::updateAllProcesses(QFlags<KSysGuard::Processes::UpdateFlag>) (src/kde/workspace/libksysguard/processcore/processes_local_p.h:57)
==60008==  Block was alloc'd at
==60008==    at 0x483EDEF: operator new(unsigned long) (vg_replace_malloc.c:342)
==60008==    by 0x1BA34F48: KSysGuard::Processes::addProcess(long, long) (src/kde/workspace/libksysguard/processcore/processes.cpp:261)
==60008==    by 0x1BA351DF: KSysGuard::Processes::updateOrAddProcess(long) (src/kde/workspace/libksysguard/processcore/processes.cpp:305)
==60008==    by 0x1BA342BF: KSysGuard::Processes::processesUpdated() (src/kde/workspace/libksysguard/processcore/processes.cpp:348)
==60008==    by 0x1BA38D50: QtPrivate::FunctorCall<QtPrivate::IndexesList<>, QtPrivate::List<>, void, void (KSysGuard::Processes::*)()>::call(void (KSysGuard::Processes::*)(), KSysGuard::Processes*, void**) (qobjectdefs_impl.h:152)
==60008==    by 0x1BA38CB7: void QtPrivate::FunctionPointer<void (KSysGuard::Processes::*)()>::call<QtPrivate::List<>, void>(void (KSysGuard::Processes::*)(), KSysGuard::Processes*, void**) (qobjectdefs_impl.h:185)
==60008==    by 0x1BA38BE4: QtPrivate::QSlotObject<void (KSysGuard::Processes::*)(), QtPrivate::List<>, void>::impl(int, QtPrivate::QSlotObjectBase*, QObject*, void**, bool*) (qobjectdefs_impl.h:418)
==60008==    by 0x794AC56: QtPrivate::QSlotObjectBase::call(QObject*, void**) (qobjectdefs_impl.h:398)
==60008==    by 0x798DF0F: void doActivate<false>(QObject*, int, void**) (qobject.cpp:3886)
==60008==    by 0x7987470: QMetaObject::activate(QObject*, QMetaObject const*, int, void**) (qobject.cpp:3946)
==60008==    by 0x1BA0B374: KSysGuard::AbstractProcesses::processesUpdated() (moc_processes_base_p.cpp:157)
==60008==    by 0x1BA4197D: KSysGuard::ProcessesLocal::updateAllProcesses(QFlags<KSysGuard::Processes::UpdateFlag>) (src/kde/workspace/libksysguard/processcore/processes_local_p.h:57)
Comment 2 David Edmundson 2021-04-09 09:11:37 UTC
Urgh, right we cache processes:

QVector<Process*> CGroupDataModelPrivate::processesFor(CGroup *app)
{
    if (m_processMap.contains(app)) {
        return m_processMap.value(app);
    }
....

but now it's shared, process objects can be deleted at any time
Comment 3 Bug Janitor Service 2021-04-09 09:25:26 UTC
A possibly relevant merge request was started @ https://invent.kde.org/plasma/libksysguard/-/merge_requests/145
Comment 4 David Edmundson 2021-04-09 09:40:28 UTC
Git commit 5e548060802cfbd43a10a7f9c18b646212f7d9c8 by David Edmundson.
Committed on 09/04/2021 at 09:40.
Pushed by davidedmundson into branch 'master'.

Clear cgroup PIDS -> process object cache whenever Processes update

Previously we wiped the cache whenever CGroupDataModel is about to call
updateAllProcesses. With the shared backend we need to clear it whenever
any part updates.

M  +7    -5    processcore/cgroup_data_model.cpp

https://invent.kde.org/plasma/libksysguard/commit/5e548060802cfbd43a10a7f9c18b646212f7d9c8