summaryrefslogtreecommitdiff
path: root/src/run
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2016-12-23 22:56:39 +0100
committerLennart Poettering <lennart@poettering.net>2017-02-02 20:59:43 +0100
commit5b1bad8d45319f45e5679d5d47be74e43ee344d3 (patch)
treedbb4caf707dc5a422c6daa5f86718bf533596abf /src/run
parent486b3d08dbf6c6b0b20e2960990f864d5d95fd37 (diff)
run: fix race for "systemd-run --wait"
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
Diffstat (limited to 'src/run')
-rw-r--r--src/run/run.c18
1 files changed, 15 insertions, 3 deletions
diff --git a/src/run/run.c b/src/run/run.c
index 99f03465b0..3e3116f235 100644
--- a/src/run/run.c
+++ b/src/run/run.c
@@ -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);