chiark / gitweb /
service: add watchdog timestamp
[elogind.git] / src / service.c
index a84cee16af9e7e06811ce8d89d52fabeea3cc5ea..d2a2dfc601d1d814d80be2e3208853c04543aeb5 100644 (file)
@@ -147,6 +147,17 @@ static void service_unwatch_main_pid(Service *s) {
         s->main_pid = 0;
 }
 
+static void service_unwatch_pid_file(Service *s) {
+        if (!s->pid_file_pathspec)
+                return;
+
+        log_debug("Stopping watch for %s's PID file %s", UNIT(s)->id, s->pid_file_pathspec->path);
+        path_spec_unwatch(s->pid_file_pathspec, UNIT(s));
+        path_spec_done(s->pid_file_pathspec);
+        free(s->pid_file_pathspec);
+        s->pid_file_pathspec = NULL;
+}
+
 static int service_set_main_pid(Service *s, pid_t pid) {
         pid_t ppid;
 
@@ -194,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);
 
@@ -222,6 +246,7 @@ static void service_done(Unit *u) {
          * our resources */
         service_unwatch_main_pid(s);
         service_unwatch_control_pid(s);
+        service_unwatch_pid_file(s);
 
         if (s->bus_name)  {
                 unit_unwatch_bus_name(u, s->bus_name);
@@ -376,7 +401,7 @@ static int sysv_fix_order(Service *s) {
                 UnitDependency d;
                 bool special_s, special_t;
 
-                t = (Service*) other;
+                t = SERVICE(other);
 
                 if (s == t)
                         continue;
@@ -1023,7 +1048,7 @@ static int fsck_fix_order(Service *s) {
                 Service *t;
                 UnitDependency d;
 
-                t = (Service*) other;
+                t = SERVICE(other);
 
                 if (s == t)
                         continue;
@@ -1389,17 +1414,6 @@ static void service_notify_sockets_dead(Service *s) {
         return;
 }
 
-static void service_unwatch_pid_file(Service *s) {
-        if (!s->pid_file_pathspec)
-                return;
-
-        log_debug("Stopping watch for %s's PID file %s", UNIT(s)->id, s->pid_file_pathspec->path);
-        path_spec_unwatch(s->pid_file_pathspec, UNIT(s));
-        path_spec_done(s->pid_file_pathspec);
-        free(s->pid_file_pathspec);
-        s->pid_file_pathspec = NULL;
-}
-
 static void service_set_state(Service *s, ServiceState state) {
         ServiceState old_state;
         assert(s);
@@ -1475,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)
@@ -2410,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;
 }
@@ -2510,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);
 
@@ -3068,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);