b7dd4d
From 3022d49ba2276eb5634d84a89a078aa3c357b70a Mon Sep 17 00:00:00 2001
b7dd4d
From: Yu Watanabe <watanabe.yu+github@gmail.com>
b7dd4d
Date: Fri, 13 Jul 2018 17:38:47 +0900
b7dd4d
Subject: [PATCH] sd-bus: make BUS_DEFAULT_TIMEOUT configurable
b7dd4d
b7dd4d
This adds sd_bus_{get,set}_method_call_timeout().
b7dd4d
If the timeout is not set or set to 0, then the timeout value is
b7dd4d
parsed from $SYSTEMD_BUS_TIMEOUT= environment variable. If the
b7dd4d
environment variable is not set, then built-in timeout is used.
b7dd4d
b7dd4d
(cherry picked from commit 385b2eb262a99373f09d01b7f5571dd71a14dc98)
b7dd4d
b7dd4d
Resolves: #2039461
b7dd4d
---
b7dd4d
 doc/ENVIRONMENT.md                   |  5 ++++
b7dd4d
 src/libsystemd/libsystemd.sym        |  7 ++++-
b7dd4d
 src/libsystemd/sd-bus/bus-internal.h |  9 ++++---
b7dd4d
 src/libsystemd/sd-bus/bus-message.c  |  7 +++--
b7dd4d
 src/libsystemd/sd-bus/sd-bus.c       | 40 ++++++++++++++++++++++++++--
b7dd4d
 src/systemd/sd-bus.h                 |  3 +++
b7dd4d
 6 files changed, 62 insertions(+), 9 deletions(-)
b7dd4d
b7dd4d
diff --git a/doc/ENVIRONMENT.md b/doc/ENVIRONMENT.md
b7dd4d
index 8d7ce6ae2c..d1a79eaa4f 100644
b7dd4d
--- a/doc/ENVIRONMENT.md
b7dd4d
+++ b/doc/ENVIRONMENT.md
b7dd4d
@@ -50,6 +50,11 @@ All tools:
b7dd4d
   this only controls use of Unicode emoji glyphs, and has no effect on other
b7dd4d
   Unicode glyphs.
b7dd4d
 
b7dd4d
+* `$SYSTEMD_BUS_TIMEOUT=SECS` — specifies the maximum time to wait for method call
b7dd4d
+  completion. If no time unit is specified, assumes seconds. The usual other units
b7dd4d
+  are understood, too (us, ms, s, min, h, d, w, month, y). If it is not set or set
b7dd4d
+  to 0, then the built-in default is used.
b7dd4d
+
b7dd4d
 systemctl:
b7dd4d
 
b7dd4d
 * `$SYSTEMCTL_FORCE_BUS=1` — if set, do not connect to PID1's private D-Bus
b7dd4d
diff --git a/src/libsystemd/libsystemd.sym b/src/libsystemd/libsystemd.sym
b7dd4d
index f4a1426248..3b55fc6473 100644
b7dd4d
--- a/src/libsystemd/libsystemd.sym
b7dd4d
+++ b/src/libsystemd/libsystemd.sym
b7dd4d
@@ -573,12 +573,17 @@ global:
b7dd4d
         sd_event_source_disable_unref;
b7dd4d
 } LIBSYSTEMD_238;
b7dd4d
 
b7dd4d
+LIBSYSTEMD_240 {
b7dd4d
+        sd_bus_set_method_call_timeout;
b7dd4d
+        sd_bus_get_method_call_timeout;
b7dd4d
+} LIBSYSTEMD_239;
b7dd4d
+
b7dd4d
 LIBSYSTEMD_248 {
b7dd4d
 global:
b7dd4d
         sd_event_source_set_ratelimit;
b7dd4d
         sd_event_source_get_ratelimit;
b7dd4d
         sd_event_source_is_ratelimited;
b7dd4d
-} LIBSYSTEMD_239;
b7dd4d
+} LIBSYSTEMD_240;
b7dd4d
 
b7dd4d
 LIBSYSTEMD_250 {
b7dd4d
 global:
b7dd4d
diff --git a/src/libsystemd/sd-bus/bus-internal.h b/src/libsystemd/sd-bus/bus-internal.h
b7dd4d
index 06bd7862cb..88415ae678 100644
b7dd4d
--- a/src/libsystemd/sd-bus/bus-internal.h
b7dd4d
+++ b/src/libsystemd/sd-bus/bus-internal.h
b7dd4d
@@ -319,6 +319,9 @@ struct sd_bus {
b7dd4d
 
b7dd4d
         int *inotify_watches;
b7dd4d
         size_t n_inotify_watches;
b7dd4d
+
b7dd4d
+        /* zero means use value specified by $SYSTEMD_BUS_TIMEOUT= environment variable or built-in default */
b7dd4d
+        usec_t method_call_timeout;
b7dd4d
 };
b7dd4d
 
b7dd4d
 /* For method calls we time-out at 25s, like in the D-Bus reference implementation */
b7dd4d
@@ -340,8 +343,7 @@ struct sd_bus {
b7dd4d
 
b7dd4d
 #define BUS_CONTAINER_DEPTH 128
b7dd4d
 
b7dd4d
-/* Defined by the specification as maximum size of an array in
b7dd4d
- * bytes */
b7dd4d
+/* Defined by the specification as maximum size of an array in bytes */
b7dd4d
 #define BUS_ARRAY_MAX_SIZE 67108864
b7dd4d
 
b7dd4d
 #define BUS_FDS_MAX 1024
b7dd4d
@@ -392,8 +394,7 @@ void bus_close_io_fds(sd_bus *b);
b7dd4d
              _slash = streq((prefix), "/") ? NULL : strrchr((prefix), '/'))
b7dd4d
 
b7dd4d
 /* If we are invoking callbacks of a bus object, ensure unreffing the
b7dd4d
- * bus from the callback doesn't destroy the object we are working
b7dd4d
- * on */
b7dd4d
+ * bus from the callback doesn't destroy the object we are working on */
b7dd4d
 #define BUS_DONT_DESTROY(bus) \
b7dd4d
         _cleanup_(sd_bus_unrefp) _unused_ sd_bus *_dont_destroy_##bus = sd_bus_ref(bus)
b7dd4d
 
b7dd4d
diff --git a/src/libsystemd/sd-bus/bus-message.c b/src/libsystemd/sd-bus/bus-message.c
b7dd4d
index 7fe8929f82..3ffe559b8d 100644
b7dd4d
--- a/src/libsystemd/sd-bus/bus-message.c
b7dd4d
+++ b/src/libsystemd/sd-bus/bus-message.c
b7dd4d
@@ -5882,8 +5882,11 @@ int bus_message_remarshal(sd_bus *bus, sd_bus_message **m) {
b7dd4d
                 return r;
b7dd4d
 
b7dd4d
         timeout = (*m)->timeout;
b7dd4d
-        if (timeout == 0 && !((*m)->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED))
b7dd4d
-                timeout = BUS_DEFAULT_TIMEOUT;
b7dd4d
+        if (timeout == 0 && !((*m)->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED)) {
b7dd4d
+                r = sd_bus_get_method_call_timeout(bus, &timeout);
b7dd4d
+                if (r < 0)
b7dd4d
+                        return r;
b7dd4d
+        }
b7dd4d
 
b7dd4d
         r = sd_bus_message_seal(n, BUS_MESSAGE_COOKIE(*m), timeout);
b7dd4d
         if (r < 0)
b7dd4d
diff --git a/src/libsystemd/sd-bus/sd-bus.c b/src/libsystemd/sd-bus/sd-bus.c
b7dd4d
index c65e24b2d1..803f3f50d6 100644
b7dd4d
--- a/src/libsystemd/sd-bus/sd-bus.c
b7dd4d
+++ b/src/libsystemd/sd-bus/sd-bus.c
b7dd4d
@@ -1651,8 +1651,11 @@ static int bus_seal_message(sd_bus *b, sd_bus_message *m, usec_t timeout) {
b7dd4d
                 return 0;
b7dd4d
         }
b7dd4d
 
b7dd4d
-        if (timeout == 0)
b7dd4d
-                timeout = BUS_DEFAULT_TIMEOUT;
b7dd4d
+        if (timeout == 0) {
b7dd4d
+                r = sd_bus_get_method_call_timeout(b, &timeout);
b7dd4d
+                if (r < 0)
b7dd4d
+                        return r;
b7dd4d
+        }
b7dd4d
 
b7dd4d
         if (!m->sender && b->patch_sender) {
b7dd4d
                 r = sd_bus_message_set_sender(m, b->patch_sender);
b7dd4d
@@ -4141,3 +4144,36 @@ _public_ int sd_bus_enqueue_for_read(sd_bus *bus, sd_bus_message *m) {
b7dd4d
         bus->rqueue[bus->rqueue_size++] = bus_message_ref_queued(m, bus);
b7dd4d
         return 0;
b7dd4d
 }
b7dd4d
+
b7dd4d
+_public_ int sd_bus_set_method_call_timeout(sd_bus *bus, uint64_t usec) {
b7dd4d
+        assert_return(bus, -EINVAL);
b7dd4d
+        assert_return(bus = bus_resolve(bus), -ENOPKG);
b7dd4d
+
b7dd4d
+        bus->method_call_timeout = usec;
b7dd4d
+        return 0;
b7dd4d
+}
b7dd4d
+
b7dd4d
+_public_ int sd_bus_get_method_call_timeout(sd_bus *bus, uint64_t *ret) {
b7dd4d
+        const char *e;
b7dd4d
+        usec_t usec;
b7dd4d
+
b7dd4d
+        assert_return(bus, -EINVAL);
b7dd4d
+        assert_return(bus = bus_resolve(bus), -ENOPKG);
b7dd4d
+        assert_return(ret, -EINVAL);
b7dd4d
+
b7dd4d
+        if (bus->method_call_timeout != 0) {
b7dd4d
+                *ret = bus->method_call_timeout;
b7dd4d
+                return 0;
b7dd4d
+        }
b7dd4d
+
b7dd4d
+        e = secure_getenv("SYSTEMD_BUS_TIMEOUT");
b7dd4d
+        if (e && parse_sec(e, &usec) >= 0 && usec != 0) {
b7dd4d
+                /* Save the parsed value to avoid multiple parsing. To change the timeout value,
b7dd4d
+                 * use sd_bus_set_method_call_timeout() instead of setenv(). */
b7dd4d
+                *ret = bus->method_call_timeout = usec;
b7dd4d
+                return 0;
b7dd4d
+        }
b7dd4d
+
b7dd4d
+        *ret = bus->method_call_timeout = BUS_DEFAULT_TIMEOUT;
b7dd4d
+        return 0;
b7dd4d
+}
b7dd4d
diff --git a/src/systemd/sd-bus.h b/src/systemd/sd-bus.h
b7dd4d
index 9ba757b13d..8b6f70bd68 100644
b7dd4d
--- a/src/systemd/sd-bus.h
b7dd4d
+++ b/src/systemd/sd-bus.h
b7dd4d
@@ -207,6 +207,9 @@ sd_event *sd_bus_get_event(sd_bus *bus);
b7dd4d
 int sd_bus_get_n_queued_read(sd_bus *bus, uint64_t *ret);
b7dd4d
 int sd_bus_get_n_queued_write(sd_bus *bus, uint64_t *ret);
b7dd4d
 
b7dd4d
+int sd_bus_set_method_call_timeout(sd_bus *bus, uint64_t usec);
b7dd4d
+int sd_bus_get_method_call_timeout(sd_bus *bus, uint64_t *ret);
b7dd4d
+
b7dd4d
 int sd_bus_add_filter(sd_bus *bus, sd_bus_slot **slot, sd_bus_message_handler_t callback, void *userdata);
b7dd4d
 int sd_bus_add_match(sd_bus *bus, sd_bus_slot **slot, const char *match, sd_bus_message_handler_t callback, void *userdata);
b7dd4d
 int sd_bus_add_match_async(sd_bus *bus, sd_bus_slot **slot, const char *match, sd_bus_message_handler_t callback, sd_bus_message_handler_t install_callback, void *userdata);