From: Simon Gardling Date: 2026-04-21 Subject: [PATCH] core/unit: reset freezer state when unit becomes inactive/failed When a frozen unit is killed via anything that delivers SIGKILL outside systemd's normal deactivation path (`systemctl kill --signal=KILL`, `kill -9`, the OOM killer, a segfault), the service transitions to failed or inactive correctly, but `u->freezer_state` is never reset. This leaves the unit permanently stuck at FreezerState=frozen: - `systemctl thaw` refuses with "Unit is not active". - `systemctl start`/`restart` refuses with "Cannot perform operation on frozen unit". - `reset-failed`, `daemon-reload`, `daemon-reexec`, and `revert` do not clear the state. The only way to recover a persistent unit in this state is to reboot. Reset the freezer state to FREEZER_RUNNING whenever a unit transitions to an inactive or failed state, and cancel any pending freeze/thaw dbus reply that will never complete. The cgroup is pruned immediately after this point, so there is nothing left to freeze; the "running" state is the correct neutral state for a dead unit. On restart, the unit will pick up its freezer state from the cgroup hierarchy again. This complements PR #38528 (stop/reset watchdog on freeze/thaw) by addressing the general SIGKILL path instead of just the watchdog- initiated kill. --- --- a/src/core/unit.c +++ b/src/core/unit.c @@ -2754,6 +2754,16 @@ SET_FLAG(u->markers, (1u << UNIT_MARKER_NEEDS_RELOAD)|(1u << UNIT_MARKER_NEEDS_RESTART), false); + + /* If the unit was frozen (or in a freezer transition) when it became inactive/failed, + * reset the freezer state to running. The cgroup is about to be pruned; leaving the + * state stuck at frozen would prevent the unit from ever being started, thawed, or + * cleared without rebooting PID 1. Also cancel any pending freeze/thaw dbus reply. */ + if (u->freezer_state != FREEZER_RUNNING) { + unit_set_freezer_state(u, FREEZER_RUNNING); + (void) bus_unit_send_pending_freezer_message(u, /* canceled= */ true); + } + unit_prune_cgroup(u); unit_unlink_state_files(u); } else if (ns != os && ns == UNIT_RELOADING)