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);
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"
#include <unistd.h>
#include "sd-id128.h"
+#include "strv.h"
#include "path-util.h"
#include "unit-name.h"
#include "bus-util.h"
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);
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;
}
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;
}
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) {