summaryrefslogtreecommitdiff
path: root/src/timedate
diff options
context:
space:
mode:
authorYu Watanabe <watanabe.yu+github@gmail.com>2018-07-27 01:32:12 +0900
committerLennart Poettering <lennart@poettering.net>2018-08-08 14:32:28 +0200
commitcf3872bd285350ef7c975d5eaba595bb2e71849d (patch)
tree4fe50f59a0926fcf6f0bc3dba802c7bdd8479d85 /src/timedate
parent9e888a9c5bb73b9636fb10a869ac69ae4537f538 (diff)
downloadsystemd-cf3872bd285350ef7c975d5eaba595bb2e71849d.tar.gz
timedate: emit property changed signal after all jobs are completed
Follow-up for 3af0a96c0fcc623bd16649fc3640396a657cf9ef (#9684).
Diffstat (limited to 'src/timedate')
-rw-r--r--src/timedate/timedated.c70
1 files changed, 40 insertions, 30 deletions
diff --git a/src/timedate/timedated.c b/src/timedate/timedated.c
index 012cbe0028..8cf5e8d48d 100644
--- a/src/timedate/timedated.c
+++ b/src/timedate/timedated.c
@@ -36,6 +36,7 @@ typedef struct UnitStatusInfo {
char *load_state;
char *unit_file_state;
char *active_state;
+ char *path;
LIST_FIELDS(struct UnitStatusInfo, units);
} UnitStatusInfo;
@@ -47,7 +48,6 @@ typedef struct Context {
sd_bus_message *cache;
sd_bus_slot *slot_job_removed;
- char *path_ntp_unit;
LIST_HEAD(UnitStatusInfo, units);
} Context;
@@ -65,6 +65,7 @@ static void unit_status_info_free(UnitStatusInfo *p) {
unit_status_info_clear(p);
free(p->name);
+ free(p->path);
free(p);
}
@@ -78,7 +79,6 @@ static void context_free(Context *c) {
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);
@@ -352,8 +352,10 @@ static int context_update_ntp_status(Context *c, sd_bus *bus, sd_bus_message *m)
}
static int match_job_removed(sd_bus_message *m, void *userdata, sd_bus_error *error) {
- const char *path;
Context *c = userdata;
+ UnitStatusInfo *u;
+ const char *path;
+ unsigned n = 0;
int r;
assert(c);
@@ -365,42 +367,30 @@ static int match_job_removed(sd_bus_message *m, void *userdata, sd_bus_error *er
return 0;
}
- if (!streq_ptr(path, c->path_ntp_unit))
- return 0;
+ LIST_FOREACH(units, u, c->units)
+ if (streq_ptr(path, u->path))
+ u->path = mfree(u->path);
+ else
+ n += !!u->path;
- (void) sd_bus_emit_properties_changed(sd_bus_message_get_bus(m), "/org/freedesktop/timedate1", "org.freedesktop.timedate1", "NTP", NULL);
+ if (n == 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);
+ c->slot_job_removed = sd_bus_slot_unref(c->slot_job_removed);
+ }
return 0;
}
-static int unit_start_or_stop(Context *c, UnitStatusInfo *u, sd_bus *bus, sd_bus_error *error, bool start) {
+static int unit_start_or_stop(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);
- /* 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);
-
- 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,
"org.freedesktop.systemd1",
@@ -419,11 +409,10 @@ static int unit_start_or_stop(Context *c, UnitStatusInfo *u, sd_bus *bus, sd_bus
if (r < 0)
return bus_log_parse_error(r);
- r = free_and_strdup(&c->path_ntp_unit, path);
+ r = free_and_strdup(&u->path, path);
if (r < 0)
return log_oom();
- c->slot_job_removed = TAKE_PTR(slot);
return 0;
}
@@ -824,6 +813,7 @@ static int method_set_time(sd_bus_message *m, void *userdata, sd_bus_error *erro
}
static int method_set_ntp(sd_bus_message *m, void *userdata, sd_bus_error *error) {
+ _cleanup_(sd_bus_slot_unrefp) sd_bus_slot *slot = NULL;
sd_bus *bus = sd_bus_message_get_bus(m);
Context *c = userdata;
UnitStatusInfo *u;
@@ -858,6 +848,23 @@ static int method_set_ntp(sd_bus_message *m, void *userdata, sd_bus_error *error
if (r == 0)
return 1;
+ /* This method may be called frequently. Forget the previous job if it has not completed yet. */
+ LIST_FOREACH(units, u, c->units)
+ u->path = mfree(u->path);
+
+ if (!c->slot_job_removed) {
+ 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;
+ }
+
if (!enable)
LIST_FOREACH(units, u, c->units) {
if (!streq(u->load_state, "loaded"))
@@ -867,7 +874,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(c, u, bus, error, enable);
+ q = unit_start_or_stop(u, bus, error, enable);
if (q < 0)
r = q;
}
@@ -881,7 +888,7 @@ static int method_set_ntp(sd_bus_message *m, void *userdata, sd_bus_error *error
if (r < 0)
continue;
- r = unit_start_or_stop(c, u, bus, error, enable);
+ r = unit_start_or_stop(u, bus, error, enable);
break;
}
@@ -891,13 +898,16 @@ static int method_set_ntp(sd_bus_message *m, void *userdata, sd_bus_error *error
!streq(u->unit_file_state, "enabled"))
continue;
- r = unit_start_or_stop(c, u, bus, error, enable);
+ r = unit_start_or_stop(u, bus, error, enable);
break;
}
if (r < 0)
return r;
+ if (slot)
+ c->slot_job_removed = TAKE_PTR(slot);
+
log_info("Set NTP to %sd", enable_disable(enable));
return sd_bus_reply_method_return(m, NULL);