[kstyle] Avoid invalid iterators in qDeleteAll
AbandonedPublic

Authored by zzag on Mar 16 2020, 1:19 PM.

Details

Reviewers
None
Group Reviewers
Plasma
Summary

When a KWindowShadow object is destroyed, it's automatically removed
from _shadows and therefore iterators become invalid. This may cause
problems when one is using qDeleteAll because the latter assumes that
the passed container won't change.

Test Plan

Applications don't crash when switching from Oxygen to
Breeze widget style.

Diff Detail

Repository
R113 Oxygen Theme
Lint
No Linters Available
Unit
No Unit Test Coverage
Build Status
Buildable 23754
Build 23772: arc lint + arc unit
zzag created this revision.Mar 16 2020, 1:19 PM
Restricted Application added a project: Plasma. · View Herald TranscriptMar 16 2020, 1:19 PM
Restricted Application added a subscriber: plasma-devel. · View Herald Transcript
zzag requested review of this revision.Mar 16 2020, 1:19 PM

Don't you access garbage then if the shadow is destroyed during qDeleteAll?

zzag added a comment.Mar 16 2020, 1:32 PM

I would say it's undefined behavior. Either way, we should not call qDeleteAll on a container which is being "simultaneously" mutated.

zzag added a comment.Mar 16 2020, 1:35 PM

it would be nice to have qSafeDeleteAll or something that takes a copy rather than a const ref.

It would be nice not to mutate a list that's being deleted

zzag added a comment.Mar 16 2020, 1:39 PM

It would be nice not to mutate a list that's being deleted

Well, we could do something like this (not sure whether it works though)

for (KWindowShadow *shadow : _shadows)
    disconnect(shadow, nullptr, this, nullptr);

qDeleteAll(_shadows);

or switch to QPointers

In D28074#628309, @zzag wrote:

Well, we could do something like this (not sure whether it works though)

for (KWindowShadow *shadow : _shadows)
    disconnect(shadow, nullptr, this, nullptr);

qDeleteAll(_shadows);

+1

zzag added a comment.Mar 16 2020, 1:45 PM

Another way around is not to use qDeleteAll, e.g.

for( QWidget* widget : _widgets )
{ unregisterWidget( widget ); } // or uninstallShadows()

Either way, I'm open to suggestions. :-)

zzag added a comment.EditedMar 16 2020, 2:14 PM

Alternatively, we could drop qDeleteAll( _widgets ); because the style is destroyed after all widgets have been deleted. So, it's sort of redundant.