diff options
| author | Ross Burton <ross.burton@arm.com> | 2024-02-13 14:22:11 +0000 |
|---|---|---|
| committer | Richard Purdie <richard.purdie@linuxfoundation.org> | 2024-02-14 13:53:36 +0000 |
| commit | 393da961be2c357a072fe5fa93ca2adf5a904c14 (patch) | |
| tree | aa1933625b15698e16ba748906956ebb5ab00d60 | |
| parent | 8da6bd69dc2f05b6eb692f9ad311f888405fbab3 (diff) | |
| download | poky-393da961be2c357a072fe5fa93ca2adf5a904c14.tar.gz | |
glib-2.0: backport memory monitor test fixes
We've been seeing the memory-monitor-dbus test case fail occasionally
on the autobuilder. Luckily there have been a series of fixes upstream
to fix races in the test case, so backport these and hopefully they
fix the issue.
[ YOCTO #15362 ]
(From OE-Core rev: 311d2606a70528e14093dd93178a2c7170718333)
Signed-off-by: Ross Burton <ross.burton@arm.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
| -rw-r--r-- | meta/recipes-core/glib-2.0/glib-2.0/memory-monitor.patch | 364 | ||||
| -rw-r--r-- | meta/recipes-core/glib-2.0/glib-2.0_2.78.3.bb | 1 |
2 files changed, 365 insertions, 0 deletions
diff --git a/meta/recipes-core/glib-2.0/glib-2.0/memory-monitor.patch b/meta/recipes-core/glib-2.0/glib-2.0/memory-monitor.patch new file mode 100644 index 0000000000..f9dfc5bb05 --- /dev/null +++ b/meta/recipes-core/glib-2.0/glib-2.0/memory-monitor.patch | |||
| @@ -0,0 +1,364 @@ | |||
| 1 | From df7506918efc8748dac8b8398021e1b79d694ba4 Mon Sep 17 00:00:00 2001 | ||
| 2 | From: Philip Withnall <philip@tecnocode.co.uk> | ||
| 3 | Date: Tue, 23 Jan 2024 11:16:52 +0000 | ||
| 4 | Subject: [PATCH] Merge branch '2887-memory-monitor-tests' into 'main' | ||
| 5 | |||
| 6 | tests: Fix race condition in memory-monitor-dbus.test | ||
| 7 | |||
| 8 | Closes #2887 | ||
| 9 | |||
| 10 | See merge request GNOME/glib!3844 | ||
| 11 | |||
| 12 | Hopefully these commits fix the occasional failures we've been seeing: | ||
| 13 | https://bugzilla.yoctoproject.org/show_bug.cgi?id=15362 | ||
| 14 | |||
| 15 | Upstream-Status: Backport | ||
| 16 | Signed-off-by: Ross Burton <ross.burton@arm.com> | ||
| 17 | --- | ||
| 18 | gio/tests/memory-monitor-dbus.py.in | 64 +++++++++++++------- | ||
| 19 | gio/tests/memory-monitor-portal.py.in | 54 ++++++++++------- | ||
| 20 | gio/tests/power-profile-monitor-dbus.py.in | 35 ++++++----- | ||
| 21 | gio/tests/power-profile-monitor-portal.py.in | 34 ++++++----- | ||
| 22 | 4 files changed, 113 insertions(+), 74 deletions(-) | ||
| 23 | |||
| 24 | diff --git a/gio/tests/memory-monitor-dbus.py.in b/gio/tests/memory-monitor-dbus.py.in | ||
| 25 | index bf3291847..7aae01e70 100755 | ||
| 26 | --- a/gio/tests/memory-monitor-dbus.py.in | ||
| 27 | +++ b/gio/tests/memory-monitor-dbus.py.in | ||
| 28 | @@ -16,7 +16,6 @@ import sys | ||
| 29 | import subprocess | ||
| 30 | import fcntl | ||
| 31 | import os | ||
| 32 | -import time | ||
| 33 | |||
| 34 | import taptestrunner | ||
| 35 | |||
| 36 | @@ -57,53 +56,74 @@ try: | ||
| 37 | fcntl.fcntl(self.p_mock.stdout, fcntl.F_SETFL, flags | os.O_NONBLOCK) | ||
| 38 | self.last_warning = -1 | ||
| 39 | self.dbusmock = dbus.Interface(self.obj_lmm, dbusmock.MOCK_IFACE) | ||
| 40 | + | ||
| 41 | + try: | ||
| 42 | + self.wait_for_bus_object('org.freedesktop.LowMemoryMonitor', | ||
| 43 | + '/org/freedesktop/LowMemoryMonitor', | ||
| 44 | + system_bus=True) | ||
| 45 | + except: | ||
| 46 | + raise | ||
| 47 | + | ||
| 48 | self.memory_monitor = Gio.MemoryMonitor.dup_default() | ||
| 49 | + assert("GMemoryMonitorDBus" in str(self.memory_monitor)) | ||
| 50 | self.memory_monitor.connect("low-memory-warning", self.memory_warning_cb) | ||
| 51 | self.mainloop = GLib.MainLoop() | ||
| 52 | self.main_context = self.mainloop.get_context() | ||
| 53 | |||
| 54 | + # The LowMemoryMonitor API is stateless: it doesn’t expose any | ||
| 55 | + # properties, just a warning signal. Emit the signal in a loop until | ||
| 56 | + # the GMemoryMonitor instance has initialised and synchronised to | ||
| 57 | + # the right state. | ||
| 58 | + def emit_warning(level): | ||
| 59 | + self.dbusmock.EmitWarning(level) | ||
| 60 | + return GLib.SOURCE_CONTINUE | ||
| 61 | + | ||
| 62 | + idle_id = GLib.idle_add(emit_warning, 0) | ||
| 63 | + while self.last_warning != 0: | ||
| 64 | + self.main_context.iteration(True) | ||
| 65 | + GLib.source_remove(idle_id) | ||
| 66 | + | ||
| 67 | def tearDown(self): | ||
| 68 | self.p_mock.terminate() | ||
| 69 | self.p_mock.wait() | ||
| 70 | |||
| 71 | - def assertEventually(self, condition, message=None, timeout=50): | ||
| 72 | + def assertEventually(self, condition, message=None, timeout=5): | ||
| 73 | '''Assert that condition function eventually returns True. | ||
| 74 | |||
| 75 | - Timeout is in deciseconds, defaulting to 50 (5 seconds). message is | ||
| 76 | + Timeout is in seconds, defaulting to 5 seconds. message is | ||
| 77 | printed on failure. | ||
| 78 | ''' | ||
| 79 | - while timeout >= 0: | ||
| 80 | - context = GLib.MainContext.default() | ||
| 81 | - while context.iteration(False): | ||
| 82 | - pass | ||
| 83 | - if condition(): | ||
| 84 | - break | ||
| 85 | - timeout -= 1 | ||
| 86 | - time.sleep(0.1) | ||
| 87 | - else: | ||
| 88 | - self.fail(message or 'timed out waiting for ' + str(condition)) | ||
| 89 | + if not message: | ||
| 90 | + message = 'timed out waiting for ' + str(condition) | ||
| 91 | + | ||
| 92 | + def timed_out_cb(message): | ||
| 93 | + self.fail(message) | ||
| 94 | + return GLib.SOURCE_REMOVE | ||
| 95 | + | ||
| 96 | + timeout_source = GLib.timeout_source_new_seconds(timeout) | ||
| 97 | + timeout_source.set_callback(timed_out_cb, message) | ||
| 98 | + timeout_source.attach(self.main_context) | ||
| 99 | + | ||
| 100 | + while not condition(): | ||
| 101 | + self.main_context.iteration(True) | ||
| 102 | + | ||
| 103 | + timeout_source.destroy() | ||
| 104 | |||
| 105 | def memory_warning_cb(self, monitor, level): | ||
| 106 | + print("Received memory warning signal, level", level) | ||
| 107 | self.last_warning = level | ||
| 108 | self.main_context.wakeup() | ||
| 109 | |||
| 110 | def test_low_memory_warning_signal(self): | ||
| 111 | '''LowMemoryWarning signal''' | ||
| 112 | |||
| 113 | - # Wait 2 seconds | ||
| 114 | - timeout = 2 | ||
| 115 | - while timeout > 0: | ||
| 116 | - time.sleep(0.5) | ||
| 117 | - timeout -= 0.5 | ||
| 118 | - self.main_context.iteration(False) | ||
| 119 | - | ||
| 120 | self.dbusmock.EmitWarning(100) | ||
| 121 | # Wait 2 seconds or until warning | ||
| 122 | - self.assertEventually(lambda: self.last_warning == 100, "'100' low-memory warning not received", 20) | ||
| 123 | + self.assertEventually(lambda: self.last_warning == 100, "'100' low-memory warning not received", 2) | ||
| 124 | |||
| 125 | self.dbusmock.EmitWarning(255) | ||
| 126 | # Wait 2 seconds or until warning | ||
| 127 | - self.assertEventually(lambda: self.last_warning == 255, "'255' low-memory warning not received", 20) | ||
| 128 | + self.assertEventually(lambda: self.last_warning == 255, "'255' low-memory warning not received", 2) | ||
| 129 | |||
| 130 | except ImportError as e: | ||
| 131 | @unittest.skip("Cannot import %s" % e.name) | ||
| 132 | diff --git a/gio/tests/memory-monitor-portal.py.in b/gio/tests/memory-monitor-portal.py.in | ||
| 133 | index 748cee850..f570508f9 100755 | ||
| 134 | --- a/gio/tests/memory-monitor-portal.py.in | ||
| 135 | +++ b/gio/tests/memory-monitor-portal.py.in | ||
| 136 | @@ -16,7 +16,6 @@ import sys | ||
| 137 | import subprocess | ||
| 138 | import fcntl | ||
| 139 | import os | ||
| 140 | -import time | ||
| 141 | |||
| 142 | import taptestrunner | ||
| 143 | |||
| 144 | @@ -80,26 +79,44 @@ try: | ||
| 145 | self.mainloop = GLib.MainLoop() | ||
| 146 | self.main_context = self.mainloop.get_context() | ||
| 147 | |||
| 148 | + # The LowMemoryMonitor API is stateless: it doesn’t expose any | ||
| 149 | + # properties, just a warning signal. Emit the signal in a loop until | ||
| 150 | + # the GMemoryMonitor instance has initialised and synchronised to | ||
| 151 | + # the right state. | ||
| 152 | + def emit_warning(level): | ||
| 153 | + self.dbusmock.EmitWarning(level) | ||
| 154 | + return GLib.SOURCE_CONTINUE | ||
| 155 | + | ||
| 156 | + idle_id = GLib.idle_add(self.emit_warning, 0) | ||
| 157 | + while self.last_warning != 0: | ||
| 158 | + self.main_context.iteration(True) | ||
| 159 | + GLib.source_remove(idle_id) | ||
| 160 | + | ||
| 161 | def tearDown(self): | ||
| 162 | self.p_mock.terminate() | ||
| 163 | self.p_mock.wait() | ||
| 164 | |||
| 165 | - def assertEventually(self, condition, message=None, timeout=50): | ||
| 166 | + def assertEventually(self, condition, message=None, timeout=5): | ||
| 167 | '''Assert that condition function eventually returns True. | ||
| 168 | |||
| 169 | - Timeout is in deciseconds, defaulting to 50 (5 seconds). message is | ||
| 170 | + Timeout is in seconds, defaulting to 5 seconds. message is | ||
| 171 | printed on failure. | ||
| 172 | ''' | ||
| 173 | - while timeout >= 0: | ||
| 174 | - context = GLib.MainContext.default() | ||
| 175 | - while context.iteration(False): | ||
| 176 | - pass | ||
| 177 | - if condition(): | ||
| 178 | - break | ||
| 179 | - timeout -= 1 | ||
| 180 | - time.sleep(0.1) | ||
| 181 | - else: | ||
| 182 | - self.fail(message or 'timed out waiting for ' + str(condition)) | ||
| 183 | + if not message: | ||
| 184 | + message = 'timed out waiting for ' + str(condition) | ||
| 185 | + | ||
| 186 | + def timed_out_cb(message): | ||
| 187 | + self.fail(message) | ||
| 188 | + return GLib.SOURCE_REMOVE | ||
| 189 | + | ||
| 190 | + timeout_source = GLib.timeout_source_new_seconds(timeout) | ||
| 191 | + timeout_source.set_callback(timed_out_cb, message) | ||
| 192 | + timeout_source.attach(self.main_context) | ||
| 193 | + | ||
| 194 | + while not condition(): | ||
| 195 | + self.main_context.iteration(True) | ||
| 196 | + | ||
| 197 | + timeout_source.destroy() | ||
| 198 | |||
| 199 | def portal_memory_warning_cb(self, monitor, level): | ||
| 200 | self.last_warning = level | ||
| 201 | @@ -108,20 +125,13 @@ try: | ||
| 202 | def test_low_memory_warning_portal_signal(self): | ||
| 203 | '''LowMemoryWarning signal''' | ||
| 204 | |||
| 205 | - # Wait 2 seconds | ||
| 206 | - timeout = 2 | ||
| 207 | - while timeout > 0: | ||
| 208 | - time.sleep(0.5) | ||
| 209 | - timeout -= 0.5 | ||
| 210 | - self.main_context.iteration(False) | ||
| 211 | - | ||
| 212 | self.dbusmock.EmitWarning(100) | ||
| 213 | # Wait 2 seconds or until warning | ||
| 214 | - self.assertEventually(lambda: self.last_warning == 100, "'100' low-memory warning not received", 20) | ||
| 215 | + self.assertEventually(lambda: self.last_warning == 100, "'100' low-memory warning not received", 2) | ||
| 216 | |||
| 217 | self.dbusmock.EmitWarning(255) | ||
| 218 | # Wait 2 seconds or until warning | ||
| 219 | - self.assertEventually(lambda: self.last_warning == 255, "'255' low-memory warning not received", 20) | ||
| 220 | + self.assertEventually(lambda: self.last_warning == 255, "'255' low-memory warning not received", 2) | ||
| 221 | |||
| 222 | except ImportError as e: | ||
| 223 | @unittest.skip("Cannot import %s" % e.name) | ||
| 224 | diff --git a/gio/tests/power-profile-monitor-dbus.py.in b/gio/tests/power-profile-monitor-dbus.py.in | ||
| 225 | index 06e594f4a..f955afc80 100755 | ||
| 226 | --- a/gio/tests/power-profile-monitor-dbus.py.in | ||
| 227 | +++ b/gio/tests/power-profile-monitor-dbus.py.in | ||
| 228 | @@ -16,7 +16,6 @@ import sys | ||
| 229 | import subprocess | ||
| 230 | import fcntl | ||
| 231 | import os | ||
| 232 | -import time | ||
| 233 | |||
| 234 | import taptestrunner | ||
| 235 | |||
| 236 | @@ -58,6 +57,7 @@ try: | ||
| 237 | self.power_saver_enabled = False | ||
| 238 | self.dbus_props = dbus.Interface(self.obj_ppd, dbus.PROPERTIES_IFACE) | ||
| 239 | self.power_profile_monitor = Gio.PowerProfileMonitor.dup_default() | ||
| 240 | + assert("GPowerProfileMonitorDBus" in str(self.power_profile_monitor)) | ||
| 241 | self.power_profile_monitor.connect("notify::power-saver-enabled", self.power_saver_enabled_cb) | ||
| 242 | self.mainloop = GLib.MainLoop() | ||
| 243 | self.main_context = self.mainloop.get_context() | ||
| 244 | @@ -66,22 +66,27 @@ try: | ||
| 245 | self.p_mock.terminate() | ||
| 246 | self.p_mock.wait() | ||
| 247 | |||
| 248 | - def assertEventually(self, condition, message=None, timeout=50): | ||
| 249 | + def assertEventually(self, condition, message=None, timeout=5): | ||
| 250 | '''Assert that condition function eventually returns True. | ||
| 251 | |||
| 252 | - Timeout is in deciseconds, defaulting to 50 (5 seconds). message is | ||
| 253 | + Timeout is in seconds, defaulting to 5 seconds. message is | ||
| 254 | printed on failure. | ||
| 255 | ''' | ||
| 256 | - while timeout >= 0: | ||
| 257 | - context = GLib.MainContext.default() | ||
| 258 | - while context.iteration(False): | ||
| 259 | - pass | ||
| 260 | - if condition(): | ||
| 261 | - break | ||
| 262 | - timeout -= 1 | ||
| 263 | - time.sleep(0.1) | ||
| 264 | - else: | ||
| 265 | - self.fail(message or 'timed out waiting for ' + str(condition)) | ||
| 266 | + if not message: | ||
| 267 | + message = 'timed out waiting for ' + str(condition) | ||
| 268 | + | ||
| 269 | + def timed_out_cb(message): | ||
| 270 | + self.fail(message) | ||
| 271 | + return GLib.SOURCE_REMOVE | ||
| 272 | + | ||
| 273 | + timeout_source = GLib.timeout_source_new_seconds(timeout) | ||
| 274 | + timeout_source.set_callback(timed_out_cb, message) | ||
| 275 | + timeout_source.attach(self.main_context) | ||
| 276 | + | ||
| 277 | + while not condition(): | ||
| 278 | + self.main_context.iteration(True) | ||
| 279 | + | ||
| 280 | + timeout_source.destroy() | ||
| 281 | |||
| 282 | def power_saver_enabled_cb(self, spec, data): | ||
| 283 | self.power_saver_enabled = self.power_profile_monitor.get_power_saver_enabled() | ||
| 284 | @@ -92,10 +97,10 @@ try: | ||
| 285 | |||
| 286 | self.assertEqual(self.power_profile_monitor.get_power_saver_enabled(), False) | ||
| 287 | self.dbus_props.Set('net.hadess.PowerProfiles', 'ActiveProfile', dbus.String('power-saver', variant_level=1)) | ||
| 288 | - self.assertEventually(lambda: self.power_saver_enabled == True, "power-saver didn't become enabled", 10) | ||
| 289 | + self.assertEventually(lambda: self.power_saver_enabled == True, "power-saver didn't become enabled", 1) | ||
| 290 | |||
| 291 | self.dbus_props.Set('net.hadess.PowerProfiles', 'ActiveProfile', dbus.String('balanced', variant_level=1)) | ||
| 292 | - self.assertEventually(lambda: self.power_saver_enabled == False, "power-saver didn't become disabled", 10) | ||
| 293 | + self.assertEventually(lambda: self.power_saver_enabled == False, "power-saver didn't become disabled", 1) | ||
| 294 | |||
| 295 | except ImportError as e: | ||
| 296 | @unittest.skip("Cannot import %s" % e.name) | ||
| 297 | diff --git a/gio/tests/power-profile-monitor-portal.py.in b/gio/tests/power-profile-monitor-portal.py.in | ||
| 298 | index 09e9a450d..ad2abf621 100755 | ||
| 299 | --- a/gio/tests/power-profile-monitor-portal.py.in | ||
| 300 | +++ b/gio/tests/power-profile-monitor-portal.py.in | ||
| 301 | @@ -16,7 +16,6 @@ import sys | ||
| 302 | import subprocess | ||
| 303 | import fcntl | ||
| 304 | import os | ||
| 305 | -import time | ||
| 306 | |||
| 307 | import taptestrunner | ||
| 308 | |||
| 309 | @@ -90,22 +89,27 @@ try: | ||
| 310 | self.p_mock.terminate() | ||
| 311 | self.p_mock.wait() | ||
| 312 | |||
| 313 | - def assertEventually(self, condition, message=None, timeout=50): | ||
| 314 | + def assertEventually(self, condition, message=None, timeout=5): | ||
| 315 | '''Assert that condition function eventually returns True. | ||
| 316 | |||
| 317 | - Timeout is in deciseconds, defaulting to 50 (5 seconds). message is | ||
| 318 | + Timeout is in seconds, defaulting to 5 seconds. message is | ||
| 319 | printed on failure. | ||
| 320 | ''' | ||
| 321 | - while timeout >= 0: | ||
| 322 | - context = GLib.MainContext.default() | ||
| 323 | - while context.iteration(False): | ||
| 324 | - pass | ||
| 325 | - if condition(): | ||
| 326 | - break | ||
| 327 | - timeout -= 1 | ||
| 328 | - time.sleep(0.1) | ||
| 329 | - else: | ||
| 330 | - self.fail(message or 'timed out waiting for ' + str(condition)) | ||
| 331 | + if not message: | ||
| 332 | + message = 'timed out waiting for ' + str(condition) | ||
| 333 | + | ||
| 334 | + def timed_out_cb(message): | ||
| 335 | + self.fail(message) | ||
| 336 | + return GLib.SOURCE_REMOVE | ||
| 337 | + | ||
| 338 | + timeout_source = GLib.timeout_source_new_seconds(timeout) | ||
| 339 | + timeout_source.set_callback(timed_out_cb, message) | ||
| 340 | + timeout_source.attach(self.main_context) | ||
| 341 | + | ||
| 342 | + while not condition(): | ||
| 343 | + self.main_context.iteration(True) | ||
| 344 | + | ||
| 345 | + timeout_source.destroy() | ||
| 346 | |||
| 347 | def power_saver_enabled_cb(self, spec, data): | ||
| 348 | self.power_saver_enabled = self.power_profile_monitor.get_power_saver_enabled() | ||
| 349 | @@ -116,10 +120,10 @@ try: | ||
| 350 | |||
| 351 | self.assertEqual(self.power_profile_monitor.get_power_saver_enabled(), False) | ||
| 352 | self.dbus_props.Set('net.hadess.PowerProfiles', 'ActiveProfile', dbus.String('power-saver', variant_level=1)) | ||
| 353 | - self.assertEventually(lambda: self.power_saver_enabled == True, "power-saver didn't become enabled", 10) | ||
| 354 | + self.assertEventually(lambda: self.power_saver_enabled == True, "power-saver didn't become enabled", 1) | ||
| 355 | |||
| 356 | self.dbus_props.Set('net.hadess.PowerProfiles', 'ActiveProfile', dbus.String('balanced', variant_level=1)) | ||
| 357 | - self.assertEventually(lambda: self.power_saver_enabled == False, "power-saver didn't become disabled", 10) | ||
| 358 | + self.assertEventually(lambda: self.power_saver_enabled == False, "power-saver didn't become disabled", 1) | ||
| 359 | |||
| 360 | def test_power_profile_power_saver_enabled_portal_default(self): | ||
| 361 | '''power-saver-enabled property default value''' | ||
| 362 | -- | ||
| 363 | 2.34.1 | ||
| 364 | |||
diff --git a/meta/recipes-core/glib-2.0/glib-2.0_2.78.3.bb b/meta/recipes-core/glib-2.0/glib-2.0_2.78.3.bb index 2729b2a596..42814ba544 100644 --- a/meta/recipes-core/glib-2.0/glib-2.0_2.78.3.bb +++ b/meta/recipes-core/glib-2.0/glib-2.0_2.78.3.bb | |||
| @@ -14,6 +14,7 @@ SRC_URI = "${GNOME_MIRROR}/glib/${SHRT_VER}/glib-${PV}.tar.xz \ | |||
| 14 | file://0001-Do-not-write-bindir-into-pkg-config-files.patch \ | 14 | file://0001-Do-not-write-bindir-into-pkg-config-files.patch \ |
| 15 | file://0001-meson-Run-atomics-test-on-clang-as-well.patch \ | 15 | file://0001-meson-Run-atomics-test-on-clang-as-well.patch \ |
| 16 | file://0001-gio-tests-resources.c-comment-out-a-build-host-only-.patch \ | 16 | file://0001-gio-tests-resources.c-comment-out-a-build-host-only-.patch \ |
| 17 | file://memory-monitor.patch \ | ||
| 17 | file://native-gtkdoc.patch \ | 18 | file://native-gtkdoc.patch \ |
| 18 | " | 19 | " |
| 19 | SRC_URI:append:class-native = " file://relocate-modules.patch \ | 20 | SRC_URI:append:class-native = " file://relocate-modules.patch \ |
