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.
@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 = '...';
<!--property CanFreeze is not documented!-->
- <!--property IgnoreOnSoftReboot is not documented!-->
-
<!--property OnSuccessJobMode is not documented!-->
<!--property OnFailureJobMode is not documented!-->
<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"/>
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>
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>
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),
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);
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 #}
* 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 */
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) {
}
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) {
* 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. */
-
- 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);
+ /* 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_REQUIRES, SPECIAL_SYSINIT_TARGET, true, UNIT_DEPENDENCY_DEFAULT);
if (r < 0)
return r;
} else {
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) {
}
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);
-
- /* 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));
+ 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;
+
+ return 0;
}
static int slice_verify(Slice *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) {
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) {
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;
}
}
- 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) {
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))
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;
"%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",
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));
}
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;
/* 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;
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);
"RefuseManualStop",
"AllowIsolate",
"IgnoreOnIsolate",
- "IgnoreOnSoftReboot",
"DefaultDependencies"))
return bus_append_parse_boolean(m, field, eq);
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
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
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)
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