summaryrefslogtreecommitdiff
path: root/src/timedate/timedated.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/timedate/timedated.c')
-rw-r--r--src/timedate/timedated.c78
1 files changed, 65 insertions, 13 deletions
diff --git a/src/timedate/timedated.c b/src/timedate/timedated.c
index 6c957646ea..012cbe0028 100644
--- a/src/timedate/timedated.c
+++ b/src/timedate/timedated.c
@@ -46,6 +46,9 @@ typedef struct Context {
Hashmap *polkit_registry;
sd_bus_message *cache;
+ sd_bus_slot *slot_job_removed;
+ char *path_ntp_unit;
+
LIST_HEAD(UnitStatusInfo, units);
} Context;
@@ -74,6 +77,9 @@ static void context_free(Context *c) {
bus_verify_polkit_async_registry_free(c->polkit_registry);
sd_bus_message_unref(c->cache);
+ sd_bus_slot_unref(c->slot_job_removed);
+ free(c->path_ntp_unit);
+
while ((p = c->units)) {
LIST_REMOVE(units, c->units, p);
unit_status_info_free(p);
@@ -345,17 +351,55 @@ static int context_update_ntp_status(Context *c, sd_bus *bus, sd_bus_message *m)
return 0;
}
-static int unit_start_or_stop(UnitStatusInfo *u, sd_bus *bus, sd_bus_error *error, bool start) {
+static int match_job_removed(sd_bus_message *m, void *userdata, sd_bus_error *error) {
+ const char *path;
+ Context *c = userdata;
+ int r;
+
+ assert(c);
+ assert(m);
+
+ r = sd_bus_message_read(m, "uoss", NULL, &path, NULL, NULL);
+ if (r < 0) {
+ bus_log_parse_error(r);
+ return 0;
+ }
+
+ if (!streq_ptr(path, c->path_ntp_unit))
+ return 0;
+
+ (void) sd_bus_emit_properties_changed(sd_bus_message_get_bus(m), "/org/freedesktop/timedate1", "org.freedesktop.timedate1", "NTP", NULL);
+
+ c->slot_job_removed = sd_bus_slot_unref(c->slot_job_removed);
+ c->path_ntp_unit = mfree(c->path_ntp_unit);
+
+ return 0;
+}
+
+static int unit_start_or_stop(Context *c, UnitStatusInfo *u, sd_bus *bus, sd_bus_error *error, bool start) {
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
+ _cleanup_(sd_bus_slot_unrefp) sd_bus_slot *slot = NULL;
+ const char *path;
int r;
+ assert(c);
assert(u);
assert(bus);
assert(error);
- /* Call context_update_ntp_status() to update UnitStatusInfo before calling this. */
+ /* This method may be called frequently. Forget the previous job if it has not completed yet. */
+ c->slot_job_removed = sd_bus_slot_unref(c->slot_job_removed);
- if (streq(u->active_state, "active") == start)
- return 0;
+ r = sd_bus_match_signal_async(
+ bus,
+ &slot,
+ "org.freedesktop.systemd1",
+ "/org/freedesktop/systemd1",
+ "org.freedesktop.systemd1.Manager",
+ "JobRemoved",
+ match_job_removed, NULL, c);
+ if (r < 0)
+ return r;
r = sd_bus_call_method(
bus,
@@ -364,13 +408,22 @@ static int unit_start_or_stop(UnitStatusInfo *u, sd_bus *bus, sd_bus_error *erro
"org.freedesktop.systemd1.Manager",
start ? "StartUnit" : "StopUnit",
error,
- NULL,
+ &reply,
"ss",
u->name,
"replace");
if (r < 0)
return r;
+ r = sd_bus_message_read(reply, "o", &path);
+ if (r < 0)
+ return bus_log_parse_error(r);
+
+ r = free_and_strdup(&c->path_ntp_unit, path);
+ if (r < 0)
+ return log_oom();
+
+ c->slot_job_removed = TAKE_PTR(slot);
return 0;
}
@@ -422,8 +475,9 @@ static int unit_enable_or_disable(UnitStatusInfo *u, sd_bus *bus, sd_bus_error *
error,
NULL,
NULL);
- if (r < 0)
- return r;
+ if (r < 0)
+ return r;
+
return 0;
}
@@ -813,7 +867,7 @@ static int method_set_ntp(sd_bus_message *m, void *userdata, sd_bus_error *error
if (q < 0)
r = q;
- q = unit_start_or_stop(u, bus, error, enable);
+ q = unit_start_or_stop(c, u, bus, error, enable);
if (q < 0)
r = q;
}
@@ -827,17 +881,17 @@ static int method_set_ntp(sd_bus_message *m, void *userdata, sd_bus_error *error
if (r < 0)
continue;
- r = unit_start_or_stop(u, bus, error, enable);
+ r = unit_start_or_stop(c, u, bus, error, enable);
break;
}
- else if (context_ntp_service_is_active(c) <= 0)
+ else
LIST_FOREACH(units, u, c->units) {
if (!streq(u->load_state, "loaded") ||
!streq(u->unit_file_state, "enabled"))
continue;
- r = unit_start_or_stop(u, bus, error, enable);
+ r = unit_start_or_stop(c, u, bus, error, enable);
break;
}
@@ -846,8 +900,6 @@ static int method_set_ntp(sd_bus_message *m, void *userdata, sd_bus_error *error
log_info("Set NTP to %sd", enable_disable(enable));
- (void) sd_bus_emit_properties_changed(bus, "/org/freedesktop/timedate1", "org.freedesktop.timedate1", "NTP", NULL);
-
return sd_bus_reply_method_return(m, NULL);
}