Merge lp:~lukas-kde/gsettings-qt/queued-processing into lp:gsettings-qt
| Status: | Merged |
|---|---|
| Approved by: | Lars Karlitski on 2015-06-02 |
| Approved revision: | 76 |
| Merged at revision: | 72 |
| Proposed branch: | lp:~lukas-kde/gsettings-qt/queued-processing |
| Merge into: | lp:gsettings-qt |
| Diff against target: |
137 lines (+65/-6) 7 files modified
GSettings/gsettings-qml.cpp (+1/-1) GSettings/gsettings-qml.h (+0/-2) gsettings-qt.pro (+1/-1) src/qgsettings.cpp (+2/-1) tests/cpptest.cpp (+35/-0) tests/cpptest.pro (+18/-0) tests/tst_GSettings.qml (+8/-1) |
| To merge this branch: | bzr merge lp:~lukas-kde/gsettings-qt/queued-processing |
| Related bugs: |
| Reviewer | Review Type | Date Requested | Status |
|---|---|---|---|
| Lars Karlitski (community) | 2015-05-22 | Approve on 2015-06-02 | |
| Nick Dedekind (community) | Approve on 2015-06-02 | ||
|
Review via email:
|
|||
Commit Message
Force handling deferred delete events to avoid memory leaks
Description of the Change
DeferredDelete events that are posted from a handler directly dispatched by glib are not run until the program exits, because Qt doesn't see them as being in the right main loop level. Force handling them here to avoid leaks until there's a fix to https:/
| Lukáš Tinkl (lukas-kde) wrote : | # |
> Thanks for the patch.
>
> Which two event loops are you talking about? Do we have a memory leak without
> this change? Please provide more detail.
There's a glib event loop handling integrated in Qt; we don't have a memory leak exactly but as
with mzanetti's previous work, the resulting QML Components are never freed when using a Loader.
> > the latter doesn't work reliably with the in-memory backend
>
> In what way is this unreliable? I added the changed signal because
> valueChanged is not emitted in all cases [1].
Try running the testcase, if you use the valueChanged() signal, it indeed does get emitted in all cases (unlike what the documentation says unfortunately)
> [1] http://
> qt/trunk/
I removed the updateKey() declaration because the implementation seems to be gone, was that an oversight?
| Lukáš Tinkl (lukas-kde) wrote : | # |
> In what way is this unreliable? I added the changed signal because
To clarify this a bit further, and this is just for the testcase, it seems that the changed signal is not emitted when using the in-memory backend gsettings backend.
| Michael Zanetti (mzanetti) wrote : | # |
Hi Lars, after some investigation we're quite sure that the changed events from gsettings are not posted to the normal Qt event loop but instead handled in a different context. This can cause all sorts of issues in Qt, one of them is the Loader issue we've been discussing in Belgium. Maybe you can think of a cleaner way to do it, but I really think we need this detaching of the signal emissions somehow.
| Lars Karlitski (larsu) wrote : | # |
I know this is on your plate right now and possibly blocking other stuff, but I can't in good conscience merge something based on conjecture.
There's a lot of integration points with glib. If there's some underlying issue with how qt uses the main loop, we ought to at least know what's going on.
Can you please provide that test case again and a more detailed explanation of what you've found so far? I might be able to have another look at this soon.
Sorry...
| Michael Zanetti (mzanetti) wrote : | # |
Here's the example: http://
Run it and then use
gsettings set com.canonical.
and
gsettings set com.canonical.
To switch between them. See how the loader leaks its item with every toggle. With everything else the Loader behaves correctly, it's really just an issue when it's hooked up to gsettings because the changed event happens in a different context than what Qt expects.
| Lars Karlitski (larsu) wrote : | # |
Thanks. I've investigated a bit and found that QEventLoop has a concept of "levels" and deferred delete events are only processed for when a given level finishes running. Calling deleteLater() from the gsettings changed signal (which runs in the level 0) makes the deferred event not run until the program exits.
There's a qt bug open about this, from ~nick-dedekind:
https:/
Queuing the signal fixes the bug as that queues it onto the correct level. That's an ok workaround, but I'd like to be more explicit and call
QCoreApplicat
in GSettingsQml:
Of course, I'd much prefer if someone fixed that upstream ;)
| Lukáš Tinkl (lukas-kde) wrote : | # |
OK, fixed using QCoreApplicatio
| Lars Karlitski (larsu) wrote : | # |
Thanks for the quick fix.
There's nothing to sync up with. Please amend the comment to something like this: "DeferredDelete events that are posted from a handler directly dispatched by glib are not run until the program exits, because Qt doesn't see them as being in the right main loop level. Force handling them here to avoid leaks until there's a fix to https:/
And change the description and commit message of this merge request.
| Nick Dedekind (nick-dedekind) wrote : | # |
Hm. not entirely sure about this.
Doesn't sending posted DeleteLater events directly break the semantics of DeleteLater?
In unitymenumodel I fixed it by queuing the events from glib loop. I'm not sure if gsetting uses synchronous sets or not? (ie. a set synchronously causes an update which we could rely on?) maybe larsu can help here.
Maybe call QMetaObject:
| Lars Karlitski (larsu) wrote : | # |
> Hm. not entirely sure about this.
>
> Doesn't sending posted DeleteLater events directly break the semantics of
> DeleteLater?
You're right, it does. Thanks for pointing that out.
> Maybe call QMetaObject:
> in qgsettings.cpp?
I didn't know you could force queued connections. Let's do that.
- 75. By Lukáš Tinkl on 2015-06-02
-
add a C++ test for the deferred deletion case
- 76. By Lukáš Tinkl on 2015-06-02
-
rename C++ test to cpptest (both target and the source)
| Nick Dedekind (nick-dedekind) wrote : | # |
Code looks good.
Tests pass.
All fine my me.
- 77. By Lukáš Tinkl on 2015-07-28
-
fix building the Cpp test in CI

Thanks for the patch.
Which two event loops are you talking about? Do we have a memory leak without this change? Please provide more detail.
> the latter doesn't work reliably with the in-memory backend
In what way is this unreliable? I added the changed signal because valueChanged is not emitted in all cases [1].
Also, please separate the unrelated changes into a separate commit.
[1] http:// bazaar. launchpad. net/~system- settings- touch/gsettings -qt/trunk/ revision/ 19