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:
parent
fe506d569d
commit
9b420b3cfb
|
@ -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"
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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) {
|
||||
|
|
Loading…
Reference in a new issue