]> git.ipfire.org Git - thirdparty/dbus.git/commitdiff
_dbus_loop_iterate: Fix OOM retry timeout handling
authorPetr Malat <oss@malat.biz>
Wed, 4 Dec 2024 09:30:24 +0000 (10:30 +0100)
committerSimon McVittie <smcv@collabora.com>
Mon, 9 Dec 2024 16:36:10 +0000 (16:36 +0000)
If there is a pending OOM watch and at the same time there is no
timeout, poll is entered with infinite timeout, because infinite
is expressed with a negative number, which is smaller than any
actual timeout.

Introduce min_poll_timeout(), which returns the smaller non-negative
number of the two, or the larger negative number if both numbers
are negative.

Resolves: https://gitlab.freedesktop.org/dbus/dbus/-/issues/536
Signed-off-by: Petr Malat <oss@malat.biz>
[smcv: adjust whitespace]
Signed-off-by: Simon McVittie <smcv@collabora.com>
dbus/dbus-mainloop.c

index 91030e3943383c40f9834f8d3599af4b91df34a5..4de5a7ae98793502b0a6499a99f8f4f36c346012 100644 (file)
@@ -562,6 +562,20 @@ _dbus_loop_queue_dispatch (DBusLoop       *loop,
     return FALSE;
 }
 
+/* Returns the smaller non-negative number of the two, or the larger negative
+ * number if both numbers are negative. Poll interprets negative timeout as
+ * infinity, which makes it longer than any actual timeout.
+ */
+static int
+min_poll_timeout (int a,
+                  int b)
+{
+  if (a < b)
+    return a < 0 ? b : a;
+  else
+    return b < 0 ? a : b;
+}
+
 /* Returns TRUE if we invoked any timeouts or have ready file
  * descriptors, which is just used in test code as a debug hack
  */
@@ -620,10 +634,7 @@ _dbus_loop_iterate (DBusLoop     *loop,
 
               check_timeout (tv_sec, tv_usec, tcb, &msecs_remaining);
 
-              if (timeout < 0)
-                timeout = msecs_remaining;
-              else
-                timeout = MIN (msecs_remaining, timeout);
+              timeout = min_poll_timeout (msecs_remaining, timeout);
 
 #if MAINLOOP_SPEW
               _dbus_verbose ("  timeout added, %d remaining, aggregate timeout %ld\n",
@@ -656,7 +667,7 @@ _dbus_loop_iterate (DBusLoop     *loop,
    * wait to re-enable it
    */
   if (loop->oom_watch_pending)
-    timeout = MIN (timeout, _dbus_get_oom_wait ());
+    timeout = min_poll_timeout (timeout, _dbus_get_oom_wait ());
 
 #if MAINLOOP_SPEW
   _dbus_verbose ("  polling on %d descriptors timeout %ld\n", _DBUS_N_ELEMENTS (ready_fds), timeout);