]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
machined: make sure to track machine unit states properly
authorLennart Poettering <lennart@poettering.net>
Tue, 28 Apr 2015 19:17:35 +0000 (21:17 +0200)
committerLennart Poettering <lennart@poettering.net>
Tue, 28 Apr 2015 19:34:23 +0000 (21:34 +0200)
If a unit is stopped for a moment, we need to invalidate our knowledge
of it, otherwise we might be confused by automatic restarts

This makes reboots for nspawn containers run as service work correctly.

https://bugs.freedesktop.org/show_bug.cgi?id=87428

src/machine/machine.c
src/machine/machine.h
src/machine/machined-dbus.c

index dd073addec20d1d2c13b8b7827f54b4db351a9ad..05fc4f849f86ae7b44dd60b0f2e47baf683c3b69 100644 (file)
@@ -80,17 +80,14 @@ void machine_free(Machine *m) {
         if (m->in_gc_queue)
                 LIST_REMOVE(gc_queue, m->manager->machine_gc_queue, m);
 
-        if (m->unit) {
-                hashmap_remove(m->manager->machine_units, m->unit);
-                free(m->unit);
-        }
+        machine_release_unit(m);
 
         free(m->scope_job);
 
-        hashmap_remove(m->manager->machines, m->name);
+        (void) hashmap_remove(m->manager->machines, m->name);
 
         if (m->leader > 0)
-                hashmap_remove_value(m->manager->machine_leaders, UINT_TO_PTR(m->leader), m);
+                (void) hashmap_remove_value(m->manager->machine_leaders, UINT_TO_PTR(m->leader), m);
 
         sd_bus_message_unref(m->create_message);
 
@@ -526,6 +523,17 @@ MachineOperation *machine_operation_unref(MachineOperation *o) {
         return NULL;
 }
 
+void machine_release_unit(Machine *m) {
+        assert(m);
+
+        if (!m->unit)
+                return;
+
+        (void) hashmap_remove(m->manager->machine_units, m->unit);
+        free(m->unit);
+        m->unit = NULL;
+}
+
 static const char* const machine_class_table[_MACHINE_CLASS_MAX] = {
         [MACHINE_CONTAINER] = "container",
         [MACHINE_VM] = "vm"
index 7b27aa27e0ec53e2e880be2f4146eef56349642b..bbe5217f657bec69a5e1cccd283e84736279560a 100644 (file)
@@ -105,6 +105,8 @@ int machine_save(Machine *m);
 int machine_load(Machine *m);
 int machine_kill(Machine *m, KillWho who, int signo);
 
+void machine_release_unit(Machine *m);
+
 MachineState machine_get_state(Machine *u);
 
 MachineOperation *machine_operation_unref(MachineOperation *o);
index 066a8da91849b36bfb8ea99485934da836c76073..76109700a34618f99e39c777424e3e6d8d9ee45b 100644 (file)
@@ -24,6 +24,7 @@
 #include <unistd.h>
 
 #include "sd-id128.h"
+#include "strv.h"
 #include "path-util.h"
 #include "unit-name.h"
 #include "bus-util.h"
@@ -923,9 +924,9 @@ int match_job_removed(sd_bus *bus, sd_bus_message *message, void *userdata, sd_b
 
 int match_properties_changed(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
         _cleanup_free_ char *unit = NULL;
+        const char *path, *interface;
         Manager *m = userdata;
         Machine *machine;
-        const char *path;
         int r;
 
         assert(bus);
@@ -939,13 +940,46 @@ int match_properties_changed(sd_bus *bus, sd_bus_message *message, void *userdat
         r = unit_name_from_dbus_path(path, &unit);
         if (r == -EINVAL) /* not for a unit */
                 return 0;
-        if (r < 0)
-                return r;
+        if (r < 0){
+                log_oom();
+                return 0;
+        }
 
         machine = hashmap_get(m->machine_units, unit);
-        if (machine)
-                machine_add_to_gc_queue(machine);
+        if (!machine)
+                return 0;
+
+        r = sd_bus_message_read(message, "s", &interface);
+        if (r < 0) {
+                bus_log_parse_error(r);
+                return 0;
+        }
+
+        if (streq(interface, "org.freedesktop.systemd1.Unit")) {
+                struct properties {
+                        char *active_state;
+                        char *sub_state;
+                } properties = {};
 
+                const struct bus_properties_map map[] = {
+                        { "ActiveState", "s", NULL, offsetof(struct properties, active_state) },
+                        { "SubState",    "s", NULL, offsetof(struct properties, sub_state)    },
+                        {}
+                };
+
+                r = bus_message_map_properties_changed(message, map, &properties);
+                if (r < 0)
+                        bus_log_parse_error(r);
+                else if (streq_ptr(properties.active_state, "inactive") ||
+                         streq_ptr(properties.active_state, "failed") ||
+                         streq_ptr(properties.sub_state, "auto-restart"))
+                        machine_release_unit(machine);
+
+                free(properties.active_state);
+                free(properties.sub_state);
+        }
+
+        machine_add_to_gc_queue(machine);
         return 0;
 }
 
@@ -962,12 +996,15 @@ int match_unit_removed(sd_bus *bus, sd_bus_message *message, void *userdata, sd_
         r = sd_bus_message_read(message, "so", &unit, &path);
         if (r < 0) {
                 bus_log_parse_error(r);
-                return r;
+                return 0;
         }
 
         machine = hashmap_get(m->machine_units, unit);
-        if (machine)
-                machine_add_to_gc_queue(machine);
+        if (!machine)
+                return 0;
+
+        machine_release_unit(machine);
+        machine_add_to_gc_queue(machine);
 
         return 0;
 }
@@ -1190,7 +1227,7 @@ int manager_unit_is_active(Manager *manager, const char *unit) {
         if (r < 0)
                 return -EINVAL;
 
-        return !streq(state, "inactive") && !streq(state, "failed");
+        return !STR_IN_SET(state, "inactive", "failed");
 }
 
 int manager_job_is_active(Manager *manager, const char *path) {