1 |
commit: d66a61b41dd7cdd605574882febfeccc4a6f292a |
2 |
Author: Andreas Sturmlechner <asturm <AT> gentoo <DOT> org> |
3 |
AuthorDate: Sun May 28 09:20:52 2017 +0000 |
4 |
Commit: Andreas Sturmlechner <asturm <AT> gentoo <DOT> org> |
5 |
CommitDate: Sun May 28 09:21:35 2017 +0000 |
6 |
URL: https://gitweb.gentoo.org/repo/gentoo.git/commit/?id=d66a61b4 |
7 |
|
8 |
kde-frameworks/bluez-qt: Fix race condition |
9 |
|
10 |
Fixes systray icons not reflecting the correct status at startup. |
11 |
|
12 |
See also: https://bugs.kde.org/show_bug.cgi?id=377405 |
13 |
|
14 |
Package-Manager: Portage-2.3.5, Repoman-2.3.1 |
15 |
|
16 |
kde-frameworks/bluez-qt/bluez-qt-5.34.0-r1.ebuild | 36 +++ |
17 |
.../files/bluez-qt-5.34.0-fix-race-condition.patch | 358 +++++++++++++++++++++ |
18 |
2 files changed, 394 insertions(+) |
19 |
|
20 |
diff --git a/kde-frameworks/bluez-qt/bluez-qt-5.34.0-r1.ebuild b/kde-frameworks/bluez-qt/bluez-qt-5.34.0-r1.ebuild |
21 |
new file mode 100644 |
22 |
index 00000000000..e6bc126ee07 |
23 |
--- /dev/null |
24 |
+++ b/kde-frameworks/bluez-qt/bluez-qt-5.34.0-r1.ebuild |
25 |
@@ -0,0 +1,36 @@ |
26 |
+# Copyright 1999-2017 Gentoo Foundation |
27 |
+# Distributed under the terms of the GNU General Public License v2 |
28 |
+ |
29 |
+EAPI=6 |
30 |
+ |
31 |
+VIRTUALX_REQUIRED="test" |
32 |
+inherit kde5 udev |
33 |
+ |
34 |
+DESCRIPTION="Qt wrapper for Bluez 5 DBus API" |
35 |
+LICENSE="LGPL-2" |
36 |
+KEYWORDS="~amd64 ~arm ~x86" |
37 |
+IUSE="" |
38 |
+ |
39 |
+DEPEND=" |
40 |
+ $(add_qt_dep qtdbus) |
41 |
+ $(add_qt_dep qtdeclarative) |
42 |
+ $(add_qt_dep qtnetwork) |
43 |
+" |
44 |
+RDEPEND="${DEPEND}" |
45 |
+ |
46 |
+PATCHES=( "${FILESDIR}/${P}-fix-race-condition.patch" ) |
47 |
+ |
48 |
+src_configure() { |
49 |
+ local mycmakeargs=( |
50 |
+ -DUDEV_RULES_INSTALL_DIR="$(get_udevdir)/rules.d" |
51 |
+ ) |
52 |
+ |
53 |
+ kde5_src_configure |
54 |
+} |
55 |
+ |
56 |
+src_test() { |
57 |
+ # bug: 609248 |
58 |
+ local myctestargs=( -j1 ) |
59 |
+ |
60 |
+ kde5_src_test |
61 |
+} |
62 |
|
63 |
diff --git a/kde-frameworks/bluez-qt/files/bluez-qt-5.34.0-fix-race-condition.patch b/kde-frameworks/bluez-qt/files/bluez-qt-5.34.0-fix-race-condition.patch |
64 |
new file mode 100644 |
65 |
index 00000000000..84f39a3c2b9 |
66 |
--- /dev/null |
67 |
+++ b/kde-frameworks/bluez-qt/files/bluez-qt-5.34.0-fix-race-condition.patch |
68 |
@@ -0,0 +1,358 @@ |
69 |
+From c02c4806c9bfcd6dc36fab6ed9873cff86681cdd Mon Sep 17 00:00:00 2001 |
70 |
+From: David Rosca <nowrep@×××××.com> |
71 |
+Date: Fri, 26 May 2017 13:55:44 +0200 |
72 |
+Subject: Fix property changes being missed immediately after an obejct is |
73 |
+ added |
74 |
+ |
75 |
+Fix race condition when property changes may be missed if the property |
76 |
+is changed immediately after the object is created. |
77 |
+The issue was that the connection to PropertyChanged signal was |
78 |
+created only after interfacesAdded signal was fired, which may have |
79 |
+already been too late. |
80 |
+This fixes it with connecting to PropertyChanged signal on all paths |
81 |
+in Manager::init(). |
82 |
+ |
83 |
+BUG: 377405 |
84 |
+ |
85 |
+Differential Revision: https://phabricator.kde.org/D5550 |
86 |
+--- |
87 |
+ autotests/fakebluez/devicemanager.cpp | 19 +++++++++++++++++++ |
88 |
+ autotests/fakebluez/devicemanager.h | 1 + |
89 |
+ autotests/managertest.cpp | 20 ++++++++++++++++++++ |
90 |
+ autotests/managertest.h | 1 + |
91 |
+ src/adapter_p.cpp | 8 -------- |
92 |
+ src/device_p.cpp | 10 +++++----- |
93 |
+ src/input.cpp | 10 +++------- |
94 |
+ src/input_p.h | 4 ---- |
95 |
+ src/manager_p.cpp | 27 +++++++++++++++++++++++++++ |
96 |
+ src/manager_p.h | 4 +++- |
97 |
+ src/mediaplayer_p.cpp | 3 --- |
98 |
+ src/utils.cpp | 7 +++++++ |
99 |
+ src/utils.h | 1 + |
100 |
+ 13 files changed, 87 insertions(+), 28 deletions(-) |
101 |
+ |
102 |
+diff --git a/autotests/fakebluez/devicemanager.cpp b/autotests/fakebluez/devicemanager.cpp |
103 |
+index 7967047..229b92a 100644 |
104 |
+--- a/autotests/fakebluez/devicemanager.cpp |
105 |
++++ b/autotests/fakebluez/devicemanager.cpp |
106 |
+@@ -43,6 +43,8 @@ void DeviceManager::runAction(const QString &actionName, const QVariantMap &prop |
107 |
+ runChangeAdapterProperty(properties); |
108 |
+ } else if (actionName == QLatin1String("change-device-property")) { |
109 |
+ runChangeDeviceProperty(properties); |
110 |
++ } else if (actionName == QLatin1String("bug377405")) { |
111 |
++ runBug377405(); |
112 |
+ } |
113 |
+ } |
114 |
+ |
115 |
+@@ -103,3 +105,20 @@ void DeviceManager::runChangeDeviceProperty(const QVariantMap &properties) |
116 |
+ |
117 |
+ device->changeProperty(properties.value(QStringLiteral("Name")).toString(), properties.value(QStringLiteral("Value"))); |
118 |
+ } |
119 |
++ |
120 |
++void DeviceManager::runBug377405() |
121 |
++{ |
122 |
++ QDBusObjectPath adapter1path = QDBusObjectPath(QStringLiteral("/org/bluez/hci0")); |
123 |
++ QVariantMap adapterProps; |
124 |
++ adapterProps[QStringLiteral("Path")] = QVariant::fromValue(adapter1path); |
125 |
++ adapterProps[QStringLiteral("Powered")] = false; |
126 |
++ |
127 |
++ runCreateAdapterAction(adapterProps); |
128 |
++ |
129 |
++ QVariantMap properties; |
130 |
++ properties[QStringLiteral("Path")] = QVariant::fromValue(adapter1path); |
131 |
++ properties[QStringLiteral("Name")] = QStringLiteral("Powered"); |
132 |
++ properties[QStringLiteral("Value")] = true; |
133 |
++ |
134 |
++ runChangeAdapterProperty(properties); |
135 |
++} |
136 |
+diff --git a/autotests/fakebluez/devicemanager.h b/autotests/fakebluez/devicemanager.h |
137 |
+index f830175..163b311 100644 |
138 |
+--- a/autotests/fakebluez/devicemanager.h |
139 |
++++ b/autotests/fakebluez/devicemanager.h |
140 |
+@@ -41,6 +41,7 @@ private: |
141 |
+ void runRemoveDeviceAction(const QVariantMap &properties); |
142 |
+ void runChangeAdapterProperty(const QVariantMap &properties); |
143 |
+ void runChangeDeviceProperty(const QVariantMap &properties); |
144 |
++ void runBug377405(); |
145 |
+ |
146 |
+ ObjectManager *m_objectManager; |
147 |
+ |
148 |
+diff --git a/autotests/managertest.cpp b/autotests/managertest.cpp |
149 |
+index 3217f97..1d7ffcc 100644 |
150 |
+--- a/autotests/managertest.cpp |
151 |
++++ b/autotests/managertest.cpp |
152 |
+@@ -437,4 +437,24 @@ void ManagerTest::bug364416() |
153 |
+ delete manager; |
154 |
+ } |
155 |
+ |
156 |
++void ManagerTest::bug377405() |
157 |
++{ |
158 |
++ // Bug 377405: Property changes immediately after adapter is added are lost |
159 |
++ |
160 |
++ FakeBluez::start(); |
161 |
++ FakeBluez::runTest(QStringLiteral("bluez-standard")); |
162 |
++ |
163 |
++ Manager *manager = new Manager; |
164 |
++ |
165 |
++ InitManagerJob *job = manager->init(); |
166 |
++ job->exec(); |
167 |
++ |
168 |
++ QVERIFY(!job->error()); |
169 |
++ |
170 |
++ FakeBluez::runAction(QStringLiteral("devicemanager"), QStringLiteral("bug377405")); |
171 |
++ |
172 |
++ // Adapter property Powered is changed to true immediately after being added |
173 |
++ QTRY_COMPARE(manager->isBluetoothOperational(), true); |
174 |
++} |
175 |
++ |
176 |
+ QTEST_MAIN(ManagerTest) |
177 |
+diff --git a/autotests/managertest.h b/autotests/managertest.h |
178 |
+index 654fe98..9de8ae1 100644 |
179 |
+--- a/autotests/managertest.h |
180 |
++++ b/autotests/managertest.h |
181 |
+@@ -41,6 +41,7 @@ private Q_SLOTS: |
182 |
+ void deviceForAddressTest(); |
183 |
+ void adapterWithDevicesRemovedTest(); |
184 |
+ void bug364416(); |
185 |
++ void bug377405(); |
186 |
+ |
187 |
+ }; |
188 |
+ |
189 |
+diff --git a/src/adapter_p.cpp b/src/adapter_p.cpp |
190 |
+index 786fa7d..eb5fa9f 100644 |
191 |
+--- a/src/adapter_p.cpp |
192 |
++++ b/src/adapter_p.cpp |
193 |
+@@ -48,14 +48,6 @@ void AdapterPrivate::init(const QVariantMap &properties) |
194 |
+ m_dbusProperties = new DBusProperties(Strings::orgBluez(), m_bluezAdapter->path(), |
195 |
+ DBusConnection::orgBluez(), this); |
196 |
+ |
197 |
+- // QueuedConnection is important here to be able to perform actions, that depend on |
198 |
+- // a previously set property, directly from slot connected to propertyChanged signal. |
199 |
+- // Eg. Powering on adapter and then starting discovery. |
200 |
+- // * with DirectConnection the StartDiscovery would fail because the adapter is still |
201 |
+- // powered off when the PropertiesChanged signal is emitted ... |
202 |
+- connect(m_dbusProperties, &DBusProperties::PropertiesChanged, |
203 |
+- this, &AdapterPrivate::propertiesChanged, Qt::QueuedConnection); |
204 |
+- |
205 |
+ // Init properties |
206 |
+ m_address = properties.value(QStringLiteral("Address")).toString(); |
207 |
+ m_name = properties.value(QStringLiteral("Name")).toString(); |
208 |
+diff --git a/src/device_p.cpp b/src/device_p.cpp |
209 |
+index 79cbb86..351162d 100644 |
210 |
+--- a/src/device_p.cpp |
211 |
++++ b/src/device_p.cpp |
212 |
+@@ -58,10 +58,6 @@ void DevicePrivate::init(const QVariantMap &properties) |
213 |
+ m_dbusProperties = new DBusProperties(Strings::orgBluez(), m_bluezDevice->path(), |
214 |
+ DBusConnection::orgBluez(), this); |
215 |
+ |
216 |
+- // QueuedConnection is important here - see AdapterPrivate::initProperties |
217 |
+- connect(m_dbusProperties, &DBusProperties::PropertiesChanged, |
218 |
+- this, &DevicePrivate::propertiesChanged, Qt::QueuedConnection); |
219 |
+- |
220 |
+ // Init properties |
221 |
+ m_address = properties.value(QStringLiteral("Address")).toString(); |
222 |
+ m_name = properties.value(QStringLiteral("Name")).toString(); |
223 |
+@@ -136,7 +132,11 @@ QDBusPendingReply<> DevicePrivate::setDBusProperty(const QString &name, const QV |
224 |
+ |
225 |
+ void DevicePrivate::propertiesChanged(const QString &interface, const QVariantMap &changed, const QStringList &invalidated) |
226 |
+ { |
227 |
+- if (interface != Strings::orgBluezDevice1()) { |
228 |
++ if (interface == Strings::orgBluezInput1() && m_input) { |
229 |
++ m_input->d->propertiesChanged(interface, changed, invalidated); |
230 |
++ } else if (interface == Strings::orgBluezMediaPlayer1() && m_mediaPlayer) { |
231 |
++ m_mediaPlayer->d->propertiesChanged(interface, changed, invalidated); |
232 |
++ } else if (interface != Strings::orgBluezDevice1()) { |
233 |
+ return; |
234 |
+ } |
235 |
+ |
236 |
+diff --git a/src/input.cpp b/src/input.cpp |
237 |
+index 4cf4f03..aabb996 100644 |
238 |
+--- a/src/input.cpp |
239 |
++++ b/src/input.cpp |
240 |
+@@ -25,11 +25,11 @@ |
241 |
+ #include "utils.h" |
242 |
+ #include "macros.h" |
243 |
+ |
244 |
++#include <QVariantMap> |
245 |
++ |
246 |
+ namespace BluezQt |
247 |
+ { |
248 |
+ |
249 |
+-typedef org::freedesktop::DBus::Properties DBusProperties; |
250 |
+- |
251 |
+ static Input::ReconnectMode stringToReconnectMode(const QString &mode) |
252 |
+ { |
253 |
+ if (mode == QLatin1String("none")) { |
254 |
+@@ -45,11 +45,7 @@ static Input::ReconnectMode stringToReconnectMode(const QString &mode) |
255 |
+ InputPrivate::InputPrivate(const QString &path, const QVariantMap &properties) |
256 |
+ : QObject() |
257 |
+ { |
258 |
+- m_dbusProperties = new DBusProperties(Strings::orgBluez(), path, |
259 |
+- DBusConnection::orgBluez(), this); |
260 |
+- |
261 |
+- connect(m_dbusProperties, &DBusProperties::PropertiesChanged, |
262 |
+- this, &InputPrivate::propertiesChanged, Qt::QueuedConnection); |
263 |
++ Q_UNUSED(path); |
264 |
+ |
265 |
+ // Init properties |
266 |
+ m_reconnectMode = stringToReconnectMode(properties.value(QStringLiteral("ReconnectMode")).toString()); |
267 |
+diff --git a/src/input_p.h b/src/input_p.h |
268 |
+index 424179a..ce3f33d 100644 |
269 |
+--- a/src/input_p.h |
270 |
++++ b/src/input_p.h |
271 |
+@@ -26,13 +26,10 @@ |
272 |
+ #include <QObject> |
273 |
+ |
274 |
+ #include "input.h" |
275 |
+-#include "dbusproperties.h" |
276 |
+ |
277 |
+ namespace BluezQt |
278 |
+ { |
279 |
+ |
280 |
+-typedef org::freedesktop::DBus::Properties DBusProperties; |
281 |
+- |
282 |
+ class InputPrivate : public QObject |
283 |
+ { |
284 |
+ Q_OBJECT |
285 |
+@@ -43,7 +40,6 @@ public: |
286 |
+ void propertiesChanged(const QString &interface, const QVariantMap &changed, const QStringList &invalidated); |
287 |
+ |
288 |
+ QWeakPointer<Input> q; |
289 |
+- DBusProperties *m_dbusProperties; |
290 |
+ |
291 |
+ Input::ReconnectMode m_reconnectMode; |
292 |
+ }; |
293 |
+diff --git a/src/manager_p.cpp b/src/manager_p.cpp |
294 |
+index aaec901..105d954 100644 |
295 |
+--- a/src/manager_p.cpp |
296 |
++++ b/src/manager_p.cpp |
297 |
+@@ -82,6 +82,13 @@ void ManagerPrivate::init() |
298 |
+ |
299 |
+ QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(DBusConnection::orgBluez().asyncCall(call)); |
300 |
+ connect(watcher, &QDBusPendingCallWatcher::finished, this, &ManagerPrivate::nameHasOwnerFinished); |
301 |
++ |
302 |
++ DBusConnection::orgBluez().connect(Strings::orgBluez(), |
303 |
++ QString(), |
304 |
++ Strings::orgFreedesktopDBusProperties(), |
305 |
++ QStringLiteral("PropertiesChanged"), |
306 |
++ this, |
307 |
++ SLOT(propertiesChanged(QString,QVariantMap,QStringList))); |
308 |
+ } |
309 |
+ |
310 |
+ void ManagerPrivate::nameHasOwnerFinished(QDBusPendingCallWatcher *watcher) |
311 |
+@@ -424,6 +431,26 @@ void ManagerPrivate::setUsableAdapter(const AdapterPtr &adapter) |
312 |
+ } |
313 |
+ } |
314 |
+ |
315 |
++void ManagerPrivate::propertiesChanged(const QString &interface, const QVariantMap &changed, const QStringList &invalidated) |
316 |
++{ |
317 |
++ // Cut anything after device path to forward it to Device to handle |
318 |
++ const QString path = message().path().section(QLatin1Char('/'), 0, 4); |
319 |
++ |
320 |
++ QTimer::singleShot(0, this, [=]() { |
321 |
++ AdapterPtr adapter = m_adapters.value(path); |
322 |
++ if (adapter) { |
323 |
++ adapter->d->propertiesChanged(interface, changed, invalidated); |
324 |
++ return; |
325 |
++ } |
326 |
++ DevicePtr device = m_devices.value(path); |
327 |
++ if (device) { |
328 |
++ device->d->propertiesChanged(interface, changed, invalidated); |
329 |
++ return; |
330 |
++ } |
331 |
++ qCDebug(BLUEZQT) << "Unhandled property change" << interface << changed << invalidated; |
332 |
++ }); |
333 |
++} |
334 |
++ |
335 |
+ void ManagerPrivate::dummy() |
336 |
+ { |
337 |
+ } |
338 |
+diff --git a/src/manager_p.h b/src/manager_p.h |
339 |
+index 0b26d1b..cc3276d 100644 |
340 |
+--- a/src/manager_p.h |
341 |
++++ b/src/manager_p.h |
342 |
+@@ -25,6 +25,7 @@ |
343 |
+ |
344 |
+ #include <QObject> |
345 |
+ #include <QHash> |
346 |
++#include <QDBusContext> |
347 |
+ |
348 |
+ #include "types.h" |
349 |
+ #include "rfkill.h" |
350 |
+@@ -44,7 +45,7 @@ class Adapter; |
351 |
+ class Device; |
352 |
+ class AdapterPrivate; |
353 |
+ |
354 |
+-class ManagerPrivate : public QObject |
355 |
++class ManagerPrivate : public QObject, protected QDBusContext |
356 |
+ { |
357 |
+ Q_OBJECT |
358 |
+ |
359 |
+@@ -96,6 +97,7 @@ Q_SIGNALS: |
360 |
+ void initFinished(); |
361 |
+ |
362 |
+ private Q_SLOTS: |
363 |
++ void propertiesChanged(const QString &interface, const QVariantMap &changed, const QStringList &invalidated); |
364 |
+ void dummy(); |
365 |
+ |
366 |
+ }; |
367 |
+diff --git a/src/mediaplayer_p.cpp b/src/mediaplayer_p.cpp |
368 |
+index 3c4e57e..21a3ebb 100644 |
369 |
+--- a/src/mediaplayer_p.cpp |
370 |
++++ b/src/mediaplayer_p.cpp |
371 |
+@@ -92,9 +92,6 @@ void MediaPlayerPrivate::init(const QVariantMap &properties) |
372 |
+ m_dbusProperties = new DBusProperties(Strings::orgBluez(), m_bluezMediaPlayer->path(), |
373 |
+ DBusConnection::orgBluez(), this); |
374 |
+ |
375 |
+- connect(m_dbusProperties, &DBusProperties::PropertiesChanged, |
376 |
+- this, &MediaPlayerPrivate::propertiesChanged, Qt::QueuedConnection); |
377 |
+- |
378 |
+ // Init properties |
379 |
+ m_name = properties.value(QStringLiteral("Name")).toString(); |
380 |
+ m_equalizer = stringToEqualizer(properties.value(QStringLiteral("Equalizer")).toString()); |
381 |
+diff --git a/src/utils.cpp b/src/utils.cpp |
382 |
+index aed8250..9ca3d6d 100644 |
383 |
+--- a/src/utils.cpp |
384 |
++++ b/src/utils.cpp |
385 |
+@@ -39,6 +39,7 @@ public: |
386 |
+ |
387 |
+ bool testRun; |
388 |
+ QString orgFreedesktopDBus; |
389 |
++ QString orgFreedesktopDBusProperties; |
390 |
+ QString orgBluez; |
391 |
+ QString orgBluezAdapter1; |
392 |
+ QString orgBluezDevice1; |
393 |
+@@ -59,6 +60,7 @@ GlobalData::GlobalData() |
394 |
+ { |
395 |
+ testRun = false; |
396 |
+ orgFreedesktopDBus = QStringLiteral("org.freedesktop.DBus"); |
397 |
++ orgFreedesktopDBusProperties = QStringLiteral("org.freedesktop.DBus.Properties"); |
398 |
+ orgBluez = QStringLiteral("org.bluez"); |
399 |
+ orgBluezAdapter1 = QStringLiteral("org.bluez.Adapter1"); |
400 |
+ orgBluezDevice1 = QStringLiteral("org.bluez.Device1"); |
401 |
+@@ -88,6 +90,11 @@ QString Strings::orgFreedesktopDBus() |
402 |
+ return globalData->orgFreedesktopDBus; |
403 |
+ } |
404 |
+ |
405 |
++QString Strings::orgFreedesktopDBusProperties() |
406 |
++{ |
407 |
++ return globalData->orgFreedesktopDBusProperties; |
408 |
++} |
409 |
++ |
410 |
+ QString Strings::orgBluez() |
411 |
+ { |
412 |
+ return globalData->orgBluez; |
413 |
+diff --git a/src/utils.h b/src/utils.h |
414 |
+index fd49d8e..08cb6b9 100644 |
415 |
+--- a/src/utils.h |
416 |
++++ b/src/utils.h |
417 |
+@@ -36,6 +36,7 @@ namespace Strings |
418 |
+ { |
419 |
+ |
420 |
+ QString orgFreedesktopDBus(); |
421 |
++QString orgFreedesktopDBusProperties(); |
422 |
+ QString orgBluez(); |
423 |
+ QString orgBluezAdapter1(); |
424 |
+ QString orgBluezDevice1(); |
425 |
+-- |
426 |
+cgit v0.11.2 |