Gracefully replace outputModel
ClosedPublic

Authored by broulik on Oct 17 2019, 1:57 PM.

Details

Summary

This patch has it signal the disappearance of the outputModel and only then deletes it.
This gives the QML side of things a chance to clean up, specifically QQuickComboBox stores the model in a QVariant and crashes if you just delete its backing model.
Ideally the model instance itself would never be replaced but just reset and populated with new outputs.

Test Plan

QQC2 ComboBox should probably be fixed to store it in a QPointer or something but this at least fixes the crash.
Opened KScreen KCM, changed something, hit "Reset", no crash

Diff Detail

Repository
R104 KScreen
Lint
Lint Skipped
Unit
Unit Tests Skipped
broulik created this revision.Oct 17 2019, 1:57 PM
Restricted Application added a project: Plasma. · View Herald TranscriptOct 17 2019, 1:57 PM
Restricted Application added a subscriber: plasma-devel. · View Herald Transcript
broulik requested review of this revision.Oct 17 2019, 1:57 PM
broulik edited the summary of this revision. (Show Details)

But just destroying and recreating is much simpler. ;)

Regarding the change: if we release without delete afterwards we leak memory. Maybe deleteLater?

But just destroying and recreating is much simpler. ;)

And causes crashes by leaving things on the QML side in an inconsistent state.

Not sure deleteLater will help you since GetConfigOperation() could take longer than that. We could perhaps delete the old model when the config operation finishes, but that might get ugly. I'll give it a shot.

Urgh, so the order of events is:

KCMKScreen::~KCMKScreen() <-- deletes the config and exposed properties
KCModuleQML::~KCModuleQML() <-- tears down the UI, which now references dangling things.

I think thats's a sign of a more generic that it would be good if we could solve, maybe an explicit method in KCModuleQML we could call from our destructor. It sounds similar to that language translation crash.

For 5.17, change to .get() to address Roman's comment and then +1 from me.

Oh I'm an idiot, I forgot to delete the model.

For me this fixes the crash when unplugging a screen with the KCM open, FWIW.

broulik updated this revision to Diff 68145.Oct 17 2019, 2:17 PM
  • Delete the old model

I call release() instead of get() so I reset the pointer to null so that when I signal outputModelChanged it returns null and QtQuick resets everything and only then I delete it.

romangg accepted this revision.Oct 17 2019, 2:25 PM

I call release() instead of get() so I reset the pointer to null so that when I signal outputModelChanged it returns null and QtQuick resets everything and only then I delete it.

Ok, this comment explains why you do it this way. An important detail for understanding what's happening is the early return of KCMKScreen::outputModel(), where null is returned in case there is no m_config. Please reformulate the comment in the code so it's more easy to understand what's going on. Thanks for the fix!

This revision is now accepted and ready to land.Oct 17 2019, 2:25 PM
This revision was automatically updated to reflect the committed changes.