]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
run: fix race for "systemd-run --wait"
authorLennart Poettering <lennart@poettering.net>
Fri, 23 Dec 2016 21:56:39 +0000 (22:56 +0100)
committerLennart Poettering <lennart@poettering.net>
Thu, 2 Feb 2017 19:59:43 +0000 (20:59 +0100)
D-Bus is inherently racy when a function returns an object path for a
newly allocated object the client shall watch: as the object already
exists before the client can subscribe to it, it might lose messages
from it.

Let's fix this, by explicitly querying unit properties right after
subscribing to its property changes.

Fixes: #4920
src/run/run.c

index 99f03465b061f0cfd5279b38feb789ed30a74313..3e3116f2355cdcfe4f873610ea3ee7ad4959ea70 100644 (file)
@@ -798,7 +798,7 @@ static void run_context_check_done(RunContext *c) {
                 sd_event_exit(c->event, EXIT_SUCCESS);
 }
 
-static int on_properties_changed(sd_bus_message *m, void *userdata, sd_bus_error *error) {
+static int run_context_update(RunContext *c, const char *path) {
 
         static const struct bus_properties_map map[] = {
                 { "ActiveState",                      "s", NULL, offsetof(RunContext, active_state)        },
@@ -811,12 +811,11 @@ static int on_properties_changed(sd_bus_message *m, void *userdata, sd_bus_error
                 {}
         };
 
-        RunContext *c = userdata;
         int r;
 
         r = bus_map_all_properties(c->bus,
                                    "org.freedesktop.systemd1",
-                                   sd_bus_message_get_path(m),
+                                   path,
                                    map,
                                    c);
         if (r < 0) {
@@ -828,6 +827,15 @@ static int on_properties_changed(sd_bus_message *m, void *userdata, sd_bus_error
         return 0;
 }
 
+static int on_properties_changed(sd_bus_message *m, void *userdata, sd_bus_error *error) {
+        RunContext *c = userdata;
+
+        assert(m);
+        assert(c);
+
+        return run_context_update(c, sd_bus_message_get_path(m));
+}
+
 static int pty_forward_handler(PTYForward *f, int rcode, void *userdata) {
         RunContext *c = userdata;
 
@@ -1027,6 +1035,10 @@ static int start_transient_service(
                         r = sd_bus_attach_event(bus, c.event, 0);
                         if (r < 0)
                                 return log_error_errno(r, "Failed to attach bus to event loop.");
+
+                        r = run_context_update(&c, path);
+                        if (r < 0)
+                                return r;
                 }
 
                 r = sd_event_loop(c.event);