diff options
author | Michael Olbrich <m.olbrich@pengutronix.de> | 2012-02-01 17:17:12 +0100 |
---|---|---|
committer | Lennart Poettering <lennart@poettering.net> | 2012-02-01 19:29:19 +0100 |
commit | a6927d7ffc18c51fbb9940f5f1e89f5c7695ed63 (patch) | |
tree | a56630fa33002013683a69126a2caec16ef31b6c /src/service.c | |
parent | c4aa65e7147dc742886edf25593e10466b02fc3a (diff) |
service: add watchdog timestamp
This patch adds WatchdogTimestamp[Monotonic] to the systemd service
D-Bus API. The timestamp is updated to the current time when the
service calls 'sd_nofity("WATCHDOG=1\n")'.
Using a timestamp instead of an 'alive' flag has two advantages:
1. No timeout is needed to define when a service is no longer alive.
This simplifies both configuration (no timeout value) and
implementation (no timeout event).
2. It is more robust. A 'dead' service might not be detected should
systemd 'forget' to reset an 'alive' flag. It is much less likely
to get a valid new timestamp if a service died.
Diffstat (limited to 'src/service.c')
-rw-r--r-- | src/service.c | 24 |
1 files changed, 24 insertions, 0 deletions
diff --git a/src/service.c b/src/service.c index 4dcd306009..d2a2dfc601 100644 --- a/src/service.c +++ b/src/service.c @@ -205,6 +205,19 @@ static void service_connection_unref(Service *s) { unit_ref_unset(&s->accept_socket); } +static void service_stop_watchdog(Service *s) { + assert(s); + + s->watchdog_timestamp.realtime = 0; + s->watchdog_timestamp.monotonic = 0; +} + +static void service_reset_watchdog(Service *s) { + assert(s); + + dual_timestamp_get(&s->watchdog_timestamp); +} + static void service_done(Unit *u) { Service *s = SERVICE(u); @@ -1476,6 +1489,9 @@ static void service_set_state(Service *s, ServiceState state) { service_connection_unref(s); } + if (state == SERVICE_STOP) + service_stop_watchdog(s); + /* For the inactive states unit_notify() will trim the cgroup, * but for exit we have to do that ourselves... */ if (state == SERVICE_EXITED && UNIT(s)->manager->n_reloading <= 0) @@ -2411,6 +2427,8 @@ static int service_serialize(Unit *u, FILE *f, FDSet *fds) { unit_serialize_item_format(u, f, "main-exec-status-status", "%i", s->main_exec_status.status); } } + if (dual_timestamp_is_set(&s->watchdog_timestamp)) + dual_timestamp_serialize(f, "watchdog-timestamp", &s->watchdog_timestamp); return 0; } @@ -2511,6 +2529,8 @@ static int service_deserialize_item(Unit *u, const char *key, const char *value, dual_timestamp_deserialize(value, &s->main_exec_status.start_timestamp); else if (streq(key, "main-exec-status-exit")) dual_timestamp_deserialize(value, &s->main_exec_status.exit_timestamp); + else if (streq(key, "watchdog-timestamp")) + dual_timestamp_deserialize(value, &s->watchdog_timestamp); else log_debug("Unknown serialization key '%s'", key); @@ -3069,6 +3089,10 @@ static void service_notify_message(Unit *u, pid_t pid, char **tags) { } } + if (strv_find(tags, "WATCHDOG=1")) { + log_debug("%s: got WATCHDOG=1", u->id); + service_reset_watchdog(s); + } /* Notify clients about changed status or main pid */ unit_add_to_dbus_queue(u); |