1
1
mirror of https://github.com/systemd/systemd-stable.git synced 2025-03-12 08:58:20 +03:00

Merge pull request #28498 from bluca/softreboot

softreboot: ensure all processes are killed
This commit is contained in:
Luca Boccassi 2023-07-24 11:36:16 +01:00 committed by GitHub
commit 291c66914f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
20 changed files with 54 additions and 180 deletions

5
NEWS
View File

@ -187,10 +187,7 @@ CHANGES WITH 254 in spe:
system reset involves. Moreover, open file descriptors may be passed
across the soft reboot into the new system where they will be passed
back to the originating services. This allows pinning resources
across the reboot, thus minimizing grey-out time further. Moreover,
it is possible to allow specific crucial services to survive the
reboot process, if they run off a separate root file system (i.e. use
RootDirectory= or RootImage=, or are portable services). This new
across the reboot, thus minimizing grey-out time further. This new
reboot mechanism is accessible via the new "systemctl soft-reboot"
command.

View File

@ -1977,8 +1977,6 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2eservice {
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b DefaultDependencies = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b IgnoreOnSoftReboot = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s OnSuccessJobMode = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s OnFailureJobMode = '...';
@ -2093,8 +2091,6 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2eservice {
<!--property CanFreeze is not documented!-->
<!--property IgnoreOnSoftReboot is not documented!-->
<!--property OnSuccessJobMode is not documented!-->
<!--property OnFailureJobMode is not documented!-->
@ -2307,8 +2303,6 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2eservice {
<variablelist class="dbus-property" generated="True" extra-ref="DefaultDependencies"/>
<variablelist class="dbus-property" generated="True" extra-ref="IgnoreOnSoftReboot"/>
<variablelist class="dbus-property" generated="True" extra-ref="OnSuccessJobMode"/>
<variablelist class="dbus-property" generated="True" extra-ref="OnFailureJobMode"/>

View File

@ -122,11 +122,6 @@
url="https://systemd.io/PORTABLE_SERVICES">Portable Services</ulink>, but make sure no resource from
the host's root filesystem is pinned via <varname>BindPaths=</varname> or similar unit settings,
otherwise the old root filesystem will be kept in memory as long as the unit is running.</para>
<para>If units shall be left running until the very end of shutdown during a soft reboot operation, but
shall be terminated regularly during other forms of shutdown, <varname>IgnoreOnSoftReboot=yes</varname>
can be set. This will ensure that soft reboot operations do not affect it, but other types of reboot
or shutdown stop it as expected.</para>
</refsect1>
<refsect1>

View File

@ -979,16 +979,6 @@
ones.</para></listitem>
</varlistentry>
<varlistentry>
<term><varname>IgnoreOnSoftReboot=</varname></term>
<listitem><para>Takes a boolean argument. Defaults to <option>no</option>. If <option>yes</option>,
the unit will be configured to survive a soft reboot operation (see:
<citerefentry><refentrytitle>systemd-soft-reboot.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>).
This will ensure the unit is stopped normally during reboot or shutdown operations, but it survives
a soft reboot by not being stopped on the way down or on the way back up.</para></listitem>
</varlistentry>
<varlistentry>
<term><varname>CollectMode=</varname></term>

View File

@ -921,7 +921,6 @@ const sd_bus_vtable bus_unit_vtable[] = {
SD_BUS_PROPERTY("RefuseManualStop", "b", bus_property_get_bool, offsetof(Unit, refuse_manual_stop), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("AllowIsolate", "b", bus_property_get_bool, offsetof(Unit, allow_isolate), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("DefaultDependencies", "b", bus_property_get_bool, offsetof(Unit, default_dependencies), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("IgnoreOnSoftReboot", "b", bus_property_get_bool, offsetof(Unit, ignore_on_soft_reboot), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("OnSuccesJobMode", "s", property_get_job_mode, offsetof(Unit, on_success_job_mode), SD_BUS_VTABLE_PROPERTY_CONST|SD_BUS_VTABLE_HIDDEN), /* deprecated */
SD_BUS_PROPERTY("OnSuccessJobMode", "s", property_get_job_mode, offsetof(Unit, on_success_job_mode), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("OnFailureJobMode", "s", property_get_job_mode, offsetof(Unit, on_failure_job_mode), SD_BUS_VTABLE_PROPERTY_CONST),
@ -2176,9 +2175,6 @@ static int bus_unit_set_transient_property(
if (streq(name, "DefaultDependencies"))
return bus_set_transient_bool(u, name, &u->default_dependencies, message, flags, error);
if (streq(name, "IgnoreOnSoftReboot"))
return bus_set_transient_bool(u, name, &u->ignore_on_soft_reboot, message, flags, error);
if (streq(name, "OnSuccessJobMode"))
return bus_set_transient_job_mode(u, name, &u->on_success_job_mode, message, flags, error);

View File

@ -312,7 +312,6 @@ Unit.RefuseManualStart, config_parse_bool,
Unit.RefuseManualStop, config_parse_bool, 0, offsetof(Unit, refuse_manual_stop)
Unit.AllowIsolate, config_parse_bool, 0, offsetof(Unit, allow_isolate)
Unit.DefaultDependencies, config_parse_bool, 0, offsetof(Unit, default_dependencies)
Unit.IgnoreOnSoftReboot, config_parse_bool, 0, offsetof(Unit, ignore_on_soft_reboot)
Unit.OnSuccessJobMode, config_parse_job_mode, 0, offsetof(Unit, on_success_job_mode)
Unit.OnFailureJobMode, config_parse_job_mode, 0, offsetof(Unit, on_failure_job_mode)
{# The following is a legacy alias name for compatibility #}

View File

@ -1871,6 +1871,9 @@ static int do_reexecute(
* SIGCHLD for them after deserializing. */
if (IN_SET(objective, MANAGER_SWITCH_ROOT, MANAGER_SOFT_REBOOT))
broadcast_signal(SIGTERM, /* wait_for_exit= */ false, /* send_sighup= */ true, arg_default_timeout_stop_usec);
/* On soft reboot really make sure nothing is left */
if (objective == MANAGER_SOFT_REBOOT)
broadcast_signal(SIGKILL, /* wait_for_exit= */ false, /* send_sighup= */ false, arg_default_timeout_stop_usec);
if (!switch_root_dir && objective == MANAGER_SOFT_REBOOT) {
/* If no switch root dir is specified, then check if /run/nextroot/ qualifies and use that */

View File

@ -342,24 +342,12 @@ static int path_add_default_dependencies(Path *p) {
return r;
if (MANAGER_IS_SYSTEM(UNIT(p)->manager)) {
r = unit_add_two_dependencies_by_name(UNIT(p),
UNIT_AFTER,
UNIT(p)->ignore_on_soft_reboot ? -EINVAL : UNIT_REQUIRES,
SPECIAL_SYSINIT_TARGET,
true,
UNIT_DEPENDENCY_DEFAULT);
r = unit_add_two_dependencies_by_name(UNIT(p), UNIT_AFTER, UNIT_REQUIRES, SPECIAL_SYSINIT_TARGET, true, UNIT_DEPENDENCY_DEFAULT);
if (r < 0)
return r;
}
if (!UNIT(p)->ignore_on_soft_reboot)
return unit_add_two_dependencies_by_name(
UNIT(p),
UNIT_BEFORE, UNIT_CONFLICTS,
SPECIAL_SHUTDOWN_TARGET, true,
UNIT_DEPENDENCY_DEFAULT);
return unit_add_dependencies_on_real_shutdown_targets(UNIT(p));
return unit_add_two_dependencies_by_name(UNIT(p), UNIT_BEFORE, UNIT_CONFLICTS, SPECIAL_SHUTDOWN_TARGET, true, UNIT_DEPENDENCY_DEFAULT);
}
static int path_add_trigger_dependencies(Path *p) {

View File

@ -131,22 +131,23 @@ static void scope_set_state(Scope *s, ScopeState state) {
}
static int scope_add_default_dependencies(Scope *s) {
int r;
assert(s);
if (!UNIT(s)->default_dependencies)
return 0;
/* Make sure scopes are unloaded on shutdown */
if (!UNIT(s)->ignore_on_soft_reboot)
return unit_add_two_dependencies_by_name(
UNIT(s),
UNIT_BEFORE, UNIT_CONFLICTS,
SPECIAL_SHUTDOWN_TARGET, true,
UNIT_DEPENDENCY_DEFAULT);
r = unit_add_two_dependencies_by_name(
UNIT(s),
UNIT_BEFORE, UNIT_CONFLICTS,
SPECIAL_SHUTDOWN_TARGET, true,
UNIT_DEPENDENCY_DEFAULT);
if (r < 0)
return r;
/* Unless we are meant to survive soft reboot, in which case we need to conflict with
* non-soft-reboot targets. */
return unit_add_dependencies_on_real_shutdown_targets(UNIT(s));
return 0;
}
static int scope_verify(Scope *s) {

View File

@ -722,16 +722,11 @@ static int service_add_default_dependencies(Service *s) {
* majority of services. */
if (MANAGER_IS_SYSTEM(UNIT(s)->manager)) {
/* First, pull in the really early boot stuff, and require it, so that we fail if we can't
* acquire it. But only add ordering if this is meant to survive a soft reboot, otherwise
* it will be pulled down. */
/* First, pull in the really early boot stuff, and
* require it, so that we fail if we can't acquire
* it. */
r = unit_add_two_dependencies_by_name(UNIT(s),
UNIT_AFTER,
UNIT(s)->ignore_on_soft_reboot ? -EINVAL : UNIT_REQUIRES,
SPECIAL_SYSINIT_TARGET,
true,
UNIT_DEPENDENCY_DEFAULT);
r = unit_add_two_dependencies_by_name(UNIT(s), UNIT_AFTER, UNIT_REQUIRES, SPECIAL_SYSINIT_TARGET, true, UNIT_DEPENDENCY_DEFAULT);
if (r < 0)
return r;
} else {
@ -752,17 +747,7 @@ static int service_add_default_dependencies(Service *s) {
return r;
/* Third, add us in for normal shutdown. */
if (!UNIT(s)->ignore_on_soft_reboot)
return unit_add_two_dependencies_by_name(UNIT(s),
UNIT_BEFORE,
UNIT_CONFLICTS,
SPECIAL_SHUTDOWN_TARGET,
true,
UNIT_DEPENDENCY_DEFAULT);
/* Unless we are meant to survive soft reboot, in which case we need to conflict with
* non-soft-reboot targets. */
return unit_add_dependencies_on_real_shutdown_targets(UNIT(s));
return unit_add_two_dependencies_by_name(UNIT(s), UNIT_BEFORE, UNIT_CONFLICTS, SPECIAL_SHUTDOWN_TARGET, true, UNIT_DEPENDENCY_DEFAULT);
}
static void service_fix_stdio(Service *s) {

View File

@ -64,22 +64,22 @@ static int slice_add_parent_slice(Slice *s) {
}
static int slice_add_default_dependencies(Slice *s) {
int r;
assert(s);
if (!UNIT(s)->default_dependencies)
return 0;
/* Make sure slices are unloaded on shutdown */
if (!UNIT(s)->ignore_on_soft_reboot)
return unit_add_two_dependencies_by_name(
UNIT(s),
UNIT_BEFORE, UNIT_CONFLICTS,
SPECIAL_SHUTDOWN_TARGET, true,
UNIT_DEPENDENCY_DEFAULT);
r = unit_add_two_dependencies_by_name(
UNIT(s),
UNIT_BEFORE, UNIT_CONFLICTS,
SPECIAL_SHUTDOWN_TARGET, true, UNIT_DEPENDENCY_DEFAULT);
if (r < 0)
return r;
/* Unless we are meant to survive soft reboot, in which case we need to conflict with
* non-soft-reboot targets. */
return unit_add_dependencies_on_real_shutdown_targets(UNIT(s));
return 0;
}
static int slice_verify(Slice *s) {

View File

@ -278,24 +278,12 @@ static int socket_add_default_dependencies(Socket *s) {
return r;
if (MANAGER_IS_SYSTEM(UNIT(s)->manager)) {
r = unit_add_two_dependencies_by_name(UNIT(s),
UNIT_AFTER,
UNIT(s)->ignore_on_soft_reboot ? -EINVAL : UNIT_REQUIRES,
SPECIAL_SYSINIT_TARGET,
true,
UNIT_DEPENDENCY_DEFAULT);
r = unit_add_two_dependencies_by_name(UNIT(s), UNIT_AFTER, UNIT_REQUIRES, SPECIAL_SYSINIT_TARGET, true, UNIT_DEPENDENCY_DEFAULT);
if (r < 0)
return r;
}
if (!UNIT(s)->ignore_on_soft_reboot)
return unit_add_two_dependencies_by_name(
UNIT(s),
UNIT_BEFORE, UNIT_CONFLICTS,
SPECIAL_SHUTDOWN_TARGET, true,
UNIT_DEPENDENCY_DEFAULT);
return unit_add_dependencies_on_real_shutdown_targets(UNIT(s));
return unit_add_two_dependencies_by_name(UNIT(s), UNIT_BEFORE, UNIT_CONFLICTS, SPECIAL_SHUTDOWN_TARGET, true, UNIT_DEPENDENCY_DEFAULT);
}
_pure_ static bool socket_has_exec(Socket *s) {

View File

@ -66,16 +66,7 @@ static int target_add_default_dependencies(Target *t) {
return 0;
/* Make sure targets are unloaded on shutdown */
if (!UNIT(t)->ignore_on_soft_reboot)
return unit_add_two_dependencies_by_name(
UNIT(t),
UNIT_BEFORE, UNIT_CONFLICTS,
SPECIAL_SHUTDOWN_TARGET, true,
UNIT_DEPENDENCY_DEFAULT);
/* Unless we are meant to survive soft reboot, in which case we need to conflict with
* non-soft-reboot targets. */
return unit_add_dependencies_on_real_shutdown_targets(UNIT(t));
return unit_add_two_dependencies_by_name(UNIT(t), UNIT_BEFORE, UNIT_CONFLICTS, SPECIAL_SHUTDOWN_TARGET, true, UNIT_DEPENDENCY_DEFAULT);
}
static int target_load(Unit *u) {

View File

@ -94,12 +94,7 @@ static int timer_add_default_dependencies(Timer *t) {
return r;
if (MANAGER_IS_SYSTEM(UNIT(t)->manager)) {
r = unit_add_two_dependencies_by_name(UNIT(t),
UNIT_AFTER,
UNIT(t)->ignore_on_soft_reboot ? -EINVAL : UNIT_REQUIRES,
SPECIAL_SYSINIT_TARGET,
true,
UNIT_DEPENDENCY_DEFAULT);
r = unit_add_two_dependencies_by_name(UNIT(t), UNIT_AFTER, UNIT_REQUIRES, SPECIAL_SYSINIT_TARGET, true, UNIT_DEPENDENCY_DEFAULT);
if (r < 0)
return r;
@ -117,14 +112,7 @@ static int timer_add_default_dependencies(Timer *t) {
}
}
if (!UNIT(t)->ignore_on_soft_reboot)
return unit_add_two_dependencies_by_name(
UNIT(t),
UNIT_BEFORE, UNIT_CONFLICTS,
SPECIAL_SHUTDOWN_TARGET, true,
UNIT_DEPENDENCY_DEFAULT);
return unit_add_dependencies_on_real_shutdown_targets(UNIT(t));
return unit_add_two_dependencies_by_name(UNIT(t), UNIT_BEFORE, UNIT_CONFLICTS, SPECIAL_SHUTDOWN_TARGET, true, UNIT_DEPENDENCY_DEFAULT);
}
static int timer_add_trigger_dependencies(Timer *t) {

View File

@ -628,7 +628,7 @@ static int transaction_apply(
HASHMAP_FOREACH(j, m->jobs) {
assert(j->installed);
if (j->unit->ignore_on_isolate || j->unit->ignore_on_soft_reboot)
if (j->unit->ignore_on_isolate)
continue;
if (hashmap_contains(tr->jobs, j->unit))
@ -1159,9 +1159,6 @@ static bool shall_stop_on_isolate(Transaction *tr, Unit *u) {
if (u->ignore_on_isolate)
return false;
if (u->ignore_on_soft_reboot)
return false;
/* Is there already something listed for this? */
if (hashmap_contains(tr->jobs, u))
return false;

View File

@ -830,7 +830,6 @@ void unit_dump(Unit *u, FILE *f, const char *prefix) {
"%s\tRefuseManualStart: %s\n"
"%s\tRefuseManualStop: %s\n"
"%s\tDefaultDependencies: %s\n"
"%s\tIgnoreOnSoftReboot: %s\n"
"%s\tOnSuccessJobMode: %s\n"
"%s\tOnFailureJobMode: %s\n"
"%s\tIgnoreOnIsolate: %s\n",
@ -838,7 +837,6 @@ void unit_dump(Unit *u, FILE *f, const char *prefix) {
prefix, yes_no(u->refuse_manual_start),
prefix, yes_no(u->refuse_manual_stop),
prefix, yes_no(u->default_dependencies),
prefix, yes_no(u->ignore_on_soft_reboot),
prefix, job_mode_to_string(u->on_success_job_mode),
prefix, job_mode_to_string(u->on_failure_job_mode),
prefix, yes_no(u->ignore_on_isolate));

View File

@ -3291,48 +3291,21 @@ int unit_add_dependency(
}
int unit_add_two_dependencies(Unit *u, UnitDependency d, UnitDependency e, Unit *other, bool add_reference, UnitDependencyMask mask) {
int r = 0, s = 0;
int r, s;
assert(u);
assert(d >= 0 || e >= 0);
if (d >= 0) {
r = unit_add_dependency(u, d, other, add_reference, mask);
if (r < 0)
return r;
}
r = unit_add_dependency(u, d, other, add_reference, mask);
if (r < 0)
return r;
if (e >= 0) {
s = unit_add_dependency(u, e, other, add_reference, mask);
if (s < 0)
return s;
}
s = unit_add_dependency(u, e, other, add_reference, mask);
if (s < 0)
return s;
return r > 0 || s > 0;
}
int unit_add_dependencies_on_real_shutdown_targets(Unit *u) {
int r;
assert(u);
STRV_FOREACH(target, STRV_MAKE(SPECIAL_REBOOT_TARGET,
SPECIAL_KEXEC_TARGET,
SPECIAL_HALT_TARGET,
SPECIAL_POWEROFF_TARGET)) {
r = unit_add_two_dependencies_by_name(u,
UNIT_BEFORE,
UNIT_CONFLICTS,
*target,
/* add_reference= */ true,
UNIT_DEPENDENCY_DEFAULT);
if (r < 0)
return r;
}
return 0;
}
static int resolve_template(Unit *u, const char *name, char **buf, const char **ret) {
int r;

View File

@ -450,9 +450,6 @@ typedef struct Unit {
/* Create default dependencies */
bool default_dependencies;
/* Configure so that the unit survives a soft reboot without stopping/starting. */
bool ignore_on_soft_reboot;
/* Refuse manual starting, allow starting only indirectly via dependency. */
bool refuse_manual_start;
@ -855,8 +852,6 @@ int unit_add_dependency_by_name(Unit *u, UnitDependency d, const char *name, boo
int unit_add_two_dependencies_by_name(Unit *u, UnitDependency d, UnitDependency e, const char *name, bool add_reference, UnitDependencyMask mask);
int unit_add_exec_dependencies(Unit *u, ExecContext *c);
/* Helper for IgnoreOnSoftReboot units that need to survive soft-reboot.target but not others */
int unit_add_dependencies_on_real_shutdown_targets(Unit *u);
int unit_choose_id(Unit *u, const char *name);
int unit_set_description(Unit *u, const char *description);

View File

@ -2521,7 +2521,6 @@ static int bus_append_unit_property(sd_bus_message *m, const char *field, const
"RefuseManualStop",
"AllowIsolate",
"IgnoreOnIsolate",
"IgnoreOnSoftReboot",
"DefaultDependencies"))
return bus_append_parse_boolean(m, field, eq);

View File

@ -20,14 +20,10 @@ if [ -f /run/testsuite82.touch3 ]; then
read -r x <&5
test "$x" = "oinkoink"
# Check that the surviving service is still around
test "$(systemctl show -P ActiveState testsuite-82-survive.service)" = "active"
# Check that no service is still around
test "$(systemctl show -P ActiveState testsuite-82-survive.service)" != "active"
test "$(systemctl show -P ActiveState testsuite-82-nosurvive.service)" != "active"
# Take out the big guns now, and kill the service via SIGKILL (SIGTERM is blocked after all, see below)
systemctl --signal=KILL kill testsuite-82-survive.service
systemctl stop testsuite-82-survive.service
# All succeeded, exit cleanly now
elif [ -f /run/testsuite82.touch2 ]; then
@ -47,8 +43,8 @@ elif [ -f /run/testsuite82.touch2 ]; then
systemd-notify --fd=3 --pid=parent 3<"$T"
rm "$T"
# Check that the surviving service is still around
test "$(systemctl show -P ActiveState testsuite-82-survive.service)" = "active"
# Check that no service is still around
test "$(systemctl show -P ActiveState testsuite-82-survive.service)" != "active"
test "$(systemctl show -P ActiveState testsuite-82-nosurvive.service)" != "active"
# Test that we really are in the new overlayfs root fs
@ -86,8 +82,8 @@ elif [ -f /run/testsuite82.touch ]; then
systemd-notify --fd=3 --pid=parent 3<"$T"
rm "$T"
# Check that the surviving service is still around
test "$(systemctl show -P ActiveState testsuite-82-survive.service)" = "active"
# Check that no service survived, regardless of the configuration
test "$(systemctl show -P ActiveState testsuite-82-survive.service)" != "active"
test "$(systemctl show -P ActiveState testsuite-82-nosurvive.service)" != "active"
# This time we test the /run/nextroot/ root switching logic. (We synthesize a new rootfs from the old via overlayfs)
@ -136,10 +132,11 @@ rm "$T"
exec sleep infinity
EOF
chmod +x "$T"
# Configure this transient unit to survive the soft reboot - it will not conflict with shutdown.target
# and it will be ignored on the isolate that happens in the next boot.
systemd-run -p Type=notify -p IgnoreOnSoftReboot=yes --unit=testsuite-82-survive.service "$T"
systemd-run -p Type=exec -p IgnoreOnSoftReboot=yes --unit=testsuite-82-nosurvive.service sleep infinity
# This sets DefaultDependencies=no so that it remains running until the
# very end, and IgnoreOnIsolate=yes so that it isn't stopped via the
# "testsuite.target" isolation we do on next boot
systemd-run -p Type=notify -p DefaultDependencies=no -p IgnoreOnIsolate=yes --unit=testsuite-82-survive.service "$T"
systemd-run -p Type=exec -p DefaultDependencies=no -p IgnoreOnIsolate=yes --unit=testsuite-82-nosurvive.service sleep infinity
# Now issue the soft reboot. We should be right back soon.
touch /run/testsuite82.touch