Merge lp:~aacid/thumbnailer/fix_dbus_blocking into lp:thumbnailer
| Status: | Merged | ||||
|---|---|---|---|---|---|
| Approved by: | Michi Henning on 2015-03-05 | ||||
| Approved revision: | 123 | ||||
| Merged at revision: | 120 | ||||
| Proposed branch: | lp:~aacid/thumbnailer/fix_dbus_blocking | ||||
| Merge into: | lp:thumbnailer | ||||
| Diff against target: |
109 lines (+26/-8) 4 files modified
plugins/Ubuntu/Thumbnailer/albumartgenerator.cpp (+9/-3) plugins/Ubuntu/Thumbnailer/albumartgenerator.h (+4/-1) plugins/Ubuntu/Thumbnailer/artistartgenerator.cpp (+9/-3) plugins/Ubuntu/Thumbnailer/artistartgenerator.h (+4/-1) |
||||
| To merge this branch: | bzr merge lp:~aacid/thumbnailer/fix_dbus_blocking | ||||
| Related bugs: |
|
| Reviewer | Review Type | Date Requested | Status |
|---|---|---|---|
| Victor Thompson (community) | Approve on 2015-03-06 | ||
| Michi Henning (community) | 2015-03-03 | Approve on 2015-03-05 | |
| PS Jenkins bot | continuous-integration | Approve on 2015-03-05 | |
| Jussi Pakkanen (community) | 2015-02-26 | Approve on 2015-02-27 | |
|
Review via email:
|
|||
Commit Message
Use own QDBusConnection
Otherwise we're using the main one that has been created in the main thread and when doing blocking calls on it, it will block on the main thread instead of in the image provided thread as we want
Description of the Change
To reproduce:
* Have a considerable amount of Music in `xdg-user-dir MUSIC`
* rm -rf ~/.cache/
* Open the My Music scope
See how UI blocks for various seconds without this patch and it's much smoother with it.
| Pete Woods (pete-woods) wrote : | # |
The only question I have here, is whether we could just use an asynchronous DBus call, and a QDBusPendingCal
| Michi Henning (michihenning) wrote : | # |
Albert, I have no objections for this as a short-term fix, if it gets you off the hook for the time being. I agree with Pete's sentiment though: if there are other requests made via the session bus from somewhere else, won't we be sending concurrent invocations into the library? (I don't know dbus well enough yet to be sure, can you help me out here?)
The library should be thread-safe, but I'm not sure whether that has been tested to any extent. Given that, an async call would probably be the more prudent way to go.
As a general remark: please don't use raw pointers. If the word "delete" appears anywhere in the code, it's a sure-fire sign that something is wrong somewhere, or will become wrong in the future (unless the code implements a resource manager or allocator). Instead, use unique_ptr or unity::
Question: Is there a particular reason to have the constructor set the two pointers to null and then lazily initialise them later? Why not just initialise in the constructor? For example, the lazy initialisation isn't thread-safe. Even if thread-safety isn't a concern, I still prefer constructors that create fully-initialised instances. That way, there cannot be any surprises (such as someone modifying the code later and forgetting to check whether the member has been initialised), and things are thread-safe for free.
| James Henstridge (jamesh) wrote : | # |
Seconding Pete's suggestion, can we just use the PendingCallWatcher interface? Looking at the docs, the following should do the trick:
QDBusPendin
watcher.
QDBusPendin
Assuming other code is playing nice with the main connection this should also solve the problem, right?
| Albert Astals Cid (aacid) wrote : | # |
> The only question I have here, is whether we could just use an asynchronous
> DBus call, and a QDBusPendingCal
> achieve async DBus, and doesn't introduce the overheads and risk of going
> multi-threaded.
You can't do an asynchronous DBus call, you need to return the image in the requestImage function of the image provider.
| Albert Astals Cid (aacid) wrote : | # |
> Albert, I have no objections for this as a short-term fix, if it gets you off
> the hook for the time being. I agree with Pete's sentiment though: if there
> are other requests made via the session bus from somewhere else, won't we be
> sending concurrent invocations into the library? (I don't know dbus well
> enough yet to be sure, can you help me out here?)
Since there's no guarantee there's a single binary using this dbus service, how is this an issue? The dbus service should be able to handle multiple calls.
>
> The library should be thread-safe, but I'm not sure whether that has been
> tested to any extent. Given that, an async call would probably be the more
> prudent way to go.
Again, how is an async call more prudent? It would just exercise the library by doing multiple calls too, so don't see how it is a [new] problem
> As a general remark: please don't use raw pointers. If the word "delete"
> appears anywhere in the code, it's a sure-fire sign that something is wrong
> somewhere, or will become wrong in the future (unless the code implements a
> resource manager or allocator). Instead, use unique_ptr or
> unity::
> deallocated, no matter what. Without this, even if the code can't throw today,
> someone may unwittingly modify it later, and a single exception that escapes
> from the bowels of the code will wreak havoc.
You must be joking right? You're telling me i can't call delete from a destructor? I'm not changing those pointers to silly pointers without a good reason for it.
> Question: Is there a particular reason to have the constructor set the two
> pointers to null and then lazily initialise them later? Why not just
> initialise in the constructor?
Because the constructor happens in the wrong thread and thus the dbus objects would belong to the main thread and still block on the main thread.
> For example, the lazy initialisation isn't
> thread-safe. Even if thread-safety isn't a concern, I still prefer
> constructors that create fully-initialised instances. That way, there cannot
> be any surprises (such as someone modifying the code later and forgetting to
> check whether the member has been initialised), and things are thread-safe for
> free.
| Albert Astals Cid (aacid) wrote : | # |
> Seconding Pete's suggestion, can we just use the PendingCallWatcher interface?
> Looking at the docs, the following should do the trick:
>
> QDBusPendingCal
> watcher.
> QDBusPendingRep
>
> Assuming other code is playing nice with the main connection this should also
> solve the problem, right?
This is exactly the same than the original code was wrottin, you're just blocking on waitForFinished() instead of in call(), what do you think this gives you?
| James Henstridge (jamesh) wrote : | # |
> This is exactly the same than the original code was wrottin, you're just
> blocking on waitForFinished() instead of in call(), what do you think this
> gives you?
Are you sure about that? I tried pulling the code out into a simple test app at http://
| Albert Astals Cid (aacid) wrote : | # |
James, your code still blocks dbus on the main thread, see http://
Idle A 0x7f7e219d0780 106
Idle B 0x7f7e219d0780 107
Idle A 0x7f7e219d0780 211
Idle B 0x7f7e219d0780 211
Idle A 0x7f7e219d0780 316
Idle B 0x7f7e219d0780 316
Idle A 0x7f7e219d0780 421
Idle B 0x7f7e219d0780 423
Idle A 0x7f7e219d0780 526
Idle B 0x7f7e219d0780 527
Idle A 0x7f7e219d0780 631
Idle B 0x7f7e219d0780 632
Idle A 0x7f7e219d0780 736
Idle B 0x7f7e219d0780 738
Idle A 0x7f7e219d0780 841
Idle B 0x7f7e219d0780 843
Idle A 0x7f7e219d0780 943
Idle B 0x7f7e219d0780 945
Making async D-Bus call (thread=
Idle A 0x7f7e219d0780 1043
Got D-Bus reply (thread=
Idle B 0x7f7e219d0780 1838
| Albert Astals Cid (aacid) wrote : | # |
That's why we need our own connection http://
Idle A 0x7ff9be0d3780 95
Idle B 0x7ff9be0d3780 96
Idle A 0x7ff9be0d3780 190
Idle B 0x7ff9be0d3780 191
Idle A 0x7ff9be0d3780 288
Idle B 0x7ff9be0d3780 289
Idle A 0x7ff9be0d3780 387
Idle B 0x7ff9be0d3780 389
Idle A 0x7ff9be0d3780 487
Idle B 0x7ff9be0d3780 489
Idle A 0x7ff9be0d3780 587
Idle B 0x7ff9be0d3780 588
Idle A 0x7ff9be0d3780 687
Idle B 0x7ff9be0d3780 688
Idle A 0x7ff9be0d3780 787
Idle B 0x7ff9be0d3780 788
Idle A 0x7ff9be0d3780 887
Idle B 0x7ff9be0d3780 889
Idle A 0x7ff9be0d3780 987
Idle B 0x7ff9be0d3780 988
Making async D-Bus call (thread=
Idle A 0x7ff9be0d3780 1087
Idle B 0x7ff9be0d3780 1088
Idle A 0x7ff9be0d3780 1187
Idle B 0x7ff9be0d3780 1189
Idle A 0x7ff9be0d3780 1287
Idle B 0x7ff9be0d3780 1288
Idle A 0x7ff9be0d3780 1387
Idle B 0x7ff9be0d3780 1389
Idle A 0x7ff9be0d3780 1487
Idle B 0x7ff9be0d3780 1488
Idle A 0x7ff9be0d3780 1587
Idle B 0x7ff9be0d3780 1589
Idle A 0x7ff9be0d3780 1687
Idle B 0x7ff9be0d3780 1688
Idle A 0x7ff9be0d3780 1787
Idle B 0x7ff9be0d3780 1788
Got D-Bus reply (thread=
| James Henstridge (jamesh) wrote : | # |
Okay. I still don't quite understand why this is causing D-Bus calls in the event loop thread to block, but it clearly is. So I guess having a second connection is necessary here.
| Michi Henning (michihenning) wrote : | # |
> You must be joking right?
No, not really.
> You're telling me i can't call delete from a
> destructor?
No. I'm suggesting that delete is almost always a bad idea and that it is almost never necessary.
> I'm not changing those pointers to silly pointers without a good
> reason for it.
Not sure why you called it a silly pointer? With unique_ptr, the constructor does not need to explicitly initialize the members, and no destructor is needed at all. That's less code, and the code is always safe.
> > Question: Is there a particular reason to have the constructor set the two
> > pointers to null and then lazily initialise them later? Why not just
> > initialise in the constructor?
>
> Because the constructor happens in the wrong thread and thus the dbus objects
> would belong to the main thread and still block on the main thread.
Ah, OK, thanks! A comment to that effect at the point of initialization would be great then.
- 121. By Albert Astals Cid on 2015-03-05
-
Comment++
- 122. By Albert Astals Cid on 2015-03-05
-
pointer nit picking
- 123. By Albert Astals Cid on 2015-03-05
-
more
| Albert Astals Cid (aacid) wrote : | # |
Updated
| PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:123
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
| Victor Thompson (vthompson) wrote : | # |
This fixes a bug filed against the music-app (lp:1428944) that has since been marked as a dupe. As a community reviewer, I approve this change from a functional standpoint since it remedies the UI blocking seen in the music app.

PASSED: Continuous integration, rev:120 jenkins. qa.ubuntu. com/job/ thumbnailer- ci/140/ jenkins. qa.ubuntu. com/job/ thumbnailer- vivid-amd64- ci/34 jenkins. qa.ubuntu. com/job/ thumbnailer- vivid-armhf- ci/32 jenkins. qa.ubuntu. com/job/ thumbnailer- vivid-armhf- ci/32/artifact/ work/output/ *zip*/output. zip jenkins. qa.ubuntu. com/job/ thumbnailer- vivid-i386- ci/29
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild: s-jenkins. ubuntu- ci:8080/ job/thumbnailer -ci/140/ rebuild
http://