summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/libelogind/sd-bus/bus-internal.h10
-rw-r--r--src/libelogind/sd-bus/bus-slot.c2
-rw-r--r--src/libelogind/sd-bus/sd-bus.c63
3 files changed, 51 insertions, 24 deletions
diff --git a/src/libelogind/sd-bus/bus-internal.h b/src/libelogind/sd-bus/bus-internal.h
index ab84dde5f..d792b39f2 100644
--- a/src/libelogind/sd-bus/bus-internal.h
+++ b/src/libelogind/sd-bus/bus-internal.h
@@ -38,7 +38,7 @@
struct reply_callback {
sd_bus_message_handler_t callback;
- usec_t timeout;
+ usec_t timeout_usec; /* this is a relative timeout until we reach the BUS_HELLO state, and an absolute one right after */
uint64_t cookie;
unsigned prioq_idx;
};
@@ -157,10 +157,10 @@ struct sd_bus_slot {
enum bus_state {
BUS_UNSET,
- BUS_WATCH_BIND, /* waiting for the socket to appear via inotify */
- BUS_OPENING,
- BUS_AUTHENTICATING,
- BUS_HELLO,
+ BUS_WATCH_BIND, /* waiting for the socket to appear via inotify */
+ BUS_OPENING, /* the kernel's connect() is still not ready */
+ BUS_AUTHENTICATING, /* we are currently in the "SASL" authorization phase of dbus */
+ BUS_HELLO, /* we are waiting for the Hello() response */
BUS_RUNNING,
BUS_CLOSING,
BUS_CLOSED
diff --git a/src/libelogind/sd-bus/bus-slot.c b/src/libelogind/sd-bus/bus-slot.c
index 756761c3e..f8de699b3 100644
--- a/src/libelogind/sd-bus/bus-slot.c
+++ b/src/libelogind/sd-bus/bus-slot.c
@@ -81,7 +81,7 @@ void bus_slot_disconnect(sd_bus_slot *slot) {
if (slot->reply_callback.cookie != 0)
ordered_hashmap_remove(slot->bus->reply_callbacks, &slot->reply_callback.cookie);
- if (slot->reply_callback.timeout != 0)
+ if (slot->reply_callback.timeout_usec != 0)
prioq_remove(slot->bus->reply_callbacks_prioq, &slot->reply_callback, &slot->reply_callback.prioq_idx);
break;
diff --git a/src/libelogind/sd-bus/sd-bus.c b/src/libelogind/sd-bus/sd-bus.c
index 380881972..d34eccd77 100644
--- a/src/libelogind/sd-bus/sd-bus.c
+++ b/src/libelogind/sd-bus/sd-bus.c
@@ -466,7 +466,24 @@ static int bus_send_hello(sd_bus *bus) {
}
int bus_start_running(sd_bus *bus) {
+ struct reply_callback *c;
+ Iterator i;
+ usec_t n;
+
assert(bus);
+ assert(bus->state < BUS_HELLO);
+
+ /* We start all method call timeouts when we enter BUS_HELLO or BUS_RUNNING mode. At this point let's convert
+ * all relative to absolute timestamps. Note that we do not reshuffle the reply callback priority queue since
+ * adding a fixed value to all entries should not alter the internal order. */
+
+ n = now(CLOCK_MONOTONIC);
+ ORDERED_HASHMAP_FOREACH(c, bus->reply_callbacks, i) {
+ if (c->timeout_usec == 0)
+ continue;
+
+ c->timeout_usec = usec_add(n, c->timeout_usec);
+ }
if (bus->bus_client) {
bus->state = BUS_HELLO;
@@ -1736,26 +1753,35 @@ _public_ int sd_bus_send_to(sd_bus *bus, sd_bus_message *m, const char *destinat
return sd_bus_send(bus, m, cookie);
}
-static usec_t calc_elapse(uint64_t usec) {
+static usec_t calc_elapse(sd_bus *bus, uint64_t usec) {
+ assert(bus);
+
if (usec == (uint64_t) -1)
return 0;
- return now(CLOCK_MONOTONIC) + usec;
+ /* We start all timeouts the instant we enter BUS_HELLO/BUS_RUNNING state, so that the don't run in parallel
+ * with any connection setup states. Hence, if a method callback is started earlier than that we just store the
+ * relative timestamp, and afterwards the absolute one. */
+
+ if (IN_SET(bus->state, BUS_WATCH_BIND, BUS_OPENING, BUS_AUTHENTICATING))
+ return usec;
+ else
+ return now(CLOCK_MONOTONIC) + usec;
}
static int timeout_compare(const void *a, const void *b) {
const struct reply_callback *x = a, *y = b;
- if (x->timeout != 0 && y->timeout == 0)
+ if (x->timeout_usec != 0 && y->timeout_usec == 0)
return -1;
- if (x->timeout == 0 && y->timeout != 0)
+ if (x->timeout_usec == 0 && y->timeout_usec != 0)
return 1;
- if (x->timeout < y->timeout)
+ if (x->timeout_usec < y->timeout_usec)
return -1;
- if (x->timeout > y->timeout)
+ if (x->timeout_usec > y->timeout_usec)
return 1;
return 0;
@@ -1815,11 +1841,11 @@ _public_ int sd_bus_call_async(
return r;
}
- s->reply_callback.timeout = calc_elapse(m->timeout);
- if (s->reply_callback.timeout != 0) {
+ s->reply_callback.timeout_usec = calc_elapse(bus, m->timeout);
+ if (s->reply_callback.timeout_usec != 0) {
r = prioq_put(bus->reply_callbacks_prioq, &s->reply_callback, &s->reply_callback.prioq_idx);
if (r < 0) {
- s->reply_callback.timeout = 0;
+ s->reply_callback.timeout_usec = 0;
return r;
}
}
@@ -1906,7 +1932,7 @@ _public_ int sd_bus_call(
if (r < 0)
goto fail;
- timeout = calc_elapse(m->timeout);
+ timeout = calc_elapse(bus, m->timeout);
for (;;) {
usec_t left;
@@ -2114,12 +2140,12 @@ _public_ int sd_bus_get_timeout(sd_bus *bus, uint64_t *timeout_usec) {
return 0;
}
- if (c->timeout == 0) {
+ if (c->timeout_usec == 0) {
*timeout_usec = (uint64_t) -1;
return 0;
}
- *timeout_usec = c->timeout;
+ *timeout_usec = c->timeout_usec;
return 1;
case BUS_CLOSING:
@@ -2146,13 +2172,14 @@ static int process_timeout(sd_bus *bus) {
int r;
assert(bus);
+ assert(IN_SET(bus->state, BUS_RUNNING, BUS_HELLO));
c = prioq_peek(bus->reply_callbacks_prioq);
if (!c)
return 0;
n = now(CLOCK_MONOTONIC);
- if (c->timeout > n)
+ if (c->timeout_usec > n)
return 0;
r = bus_message_new_synthetic_error(
@@ -2168,7 +2195,7 @@ static int process_timeout(sd_bus *bus) {
return r;
assert_se(prioq_pop(bus->reply_callbacks_prioq) == c);
- c->timeout = 0;
+ c->timeout_usec = 0;
ordered_hashmap_remove(bus->reply_callbacks, &c->cookie);
c->cookie = 0;
@@ -2279,9 +2306,9 @@ static int process_reply(sd_bus *bus, sd_bus_message *m) {
return r;
}
- if (c->timeout != 0) {
+ if (c->timeout_usec != 0) {
prioq_remove(bus->reply_callbacks_prioq, c, &c->prioq_idx);
- c->timeout = 0;
+ c->timeout_usec = 0;
}
is_hello = bus->state == BUS_HELLO && c->callback == hello_callback;
@@ -2617,9 +2644,9 @@ static int process_closing_reply_callback(sd_bus *bus, struct reply_callback *c)
if (r < 0)
return r;
- if (c->timeout != 0) {
+ if (c->timeout_usec != 0) {
prioq_remove(bus->reply_callbacks_prioq, c, &c->prioq_idx);
- c->timeout = 0;
+ c->timeout_usec = 0;
}
ordered_hashmap_remove(bus->reply_callbacks, &c->cookie);