machined: make sure to track machine unit states properly

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
This commit is contained in:
Lennart Poettering 2015-04-28 21:17:35 +02:00
parent fe506d569d
commit 9b420b3cfb
3 changed files with 62 additions and 15 deletions

View 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"

View 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);

View 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) {