diff options
Diffstat (limited to 'upstream/opensuse-tumbleweed/man8/systemd-soft-reboot.service.8')
-rw-r--r-- | upstream/opensuse-tumbleweed/man8/systemd-soft-reboot.service.8 | 319 |
1 files changed, 301 insertions, 18 deletions
diff --git a/upstream/opensuse-tumbleweed/man8/systemd-soft-reboot.service.8 b/upstream/opensuse-tumbleweed/man8/systemd-soft-reboot.service.8 index 84476beb..6aa6122f 100644 --- a/upstream/opensuse-tumbleweed/man8/systemd-soft-reboot.service.8 +++ b/upstream/opensuse-tumbleweed/man8/systemd-soft-reboot.service.8 @@ -1,5 +1,5 @@ '\" t -.TH "SYSTEMD\-SOFT\-REBOOT\&.SERVICE" "8" "" "systemd 254" "systemd-soft-reboot.service" +.TH "SYSTEMD\-SOFT\-REBOOT\&.SERVICE" "8" "" "systemd 255" "systemd-soft-reboot.service" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- @@ -31,8 +31,8 @@ is a system service that is pulled in by soft\-reboot\&.target and is responsible for performing a userspace\-only reboot operation\&. When invoked, it will send the \fBSIGTERM\fR -signal to any processes left running (but does not follow up with -\fBSIGKILL\fR, and does not wait for the processes to exit)\&. If the +signal to any processes left running (but does not wait for the processes to exit), and follow up with +\fBSIGKILL\fR\&. If the /run/nextroot/ directory exists (which may be a regular directory, a directory mount point or a symlink to either) then it will switch the file system root to it\&. It then reexecutes the service manager off the (possibly now new) root file system, which will enqueue a new boot transaction as in a normal reboot\&. .PP @@ -60,7 +60,7 @@ The second phase of regular shutdown, as implemented by .sp -1 .IP \(bu 2.3 .\} -The third phase of regular shutdown, i\&.e\&. the return to the initrd context +The third phase of regular shutdown, i\&.e\&. the return to the initrd context\&. .RE .sp .RS 4 @@ -71,7 +71,7 @@ The third phase of regular shutdown, i\&.e\&. the return to the initrd context .sp -1 .IP \(bu 2.3 .\} -The hardware reboot operation +The hardware reboot operation\&. .RE .sp .RS 4 @@ -82,7 +82,7 @@ The hardware reboot operation .sp -1 .IP \(bu 2.3 .\} -The firmware initialization +The firmware initialization\&. .RE .sp .RS 4 @@ -93,7 +93,7 @@ The firmware initialization .sp -1 .IP \(bu 2.3 .\} -The boot loader initialization +The boot loader initialization\&. .RE .sp .RS 4 @@ -104,7 +104,7 @@ The boot loader initialization .sp -1 .IP \(bu 2.3 .\} -The kernel initialization +The kernel initialization\&. .RE .sp .RS 4 @@ -115,7 +115,7 @@ The kernel initialization .sp -1 .IP \(bu 2.3 .\} -The initrd initialization +The initrd initialization\&. .RE .PP However this form of reboot comes with drawbacks as well: @@ -207,11 +207,48 @@ file system remains mounted and populated and may be used to pass state informat .sp -1 .IP \(bu 2.3 .\} -Service processes may continue to run over the transition, if they are placed in services that remain active until the very end of shutdown (which again is achieved via +Service processes may continue to run over the transition, past soft\-reboot and into the next session, if they are placed in services that remain active until the very end of shutdown (which again is achieved via \fIDefaultDependencies=no\fR)\&. They must also be set up to avoid being killed by the aforementioned \fBSIGTERM\fR -spree (as per -\m[blue]\fBsystemd and Storage Daemons for the Root File System\fR\m[]\&\s-2\u[1]\d\s+2)\&. +and +\fBSIGKILL\fR +via +\fISurviveFinalKillSignal=yes\fR, and also be configured to avoid being stopped on isolate via +\fIIgnoreOnIsolate=yes\fR\&. They also have to be configured to be stopped on normal shutdown, reboot and maintenance mode\&. Finally, they have to be ordered after +\fBbasic\&.target\fR +to ensure correct ordering on boot\&. Note that in case any new or custom units are used to isolate to, or that implement an equivalent shutdown functionality, they will also have to be configured manually for correct ordering and conflicting\&. For example: +.sp +.if n \{\ +.RS 4 +.\} +.nf +[Unit] +Description=My surviving service +SurviveFinalKillSignal=yes +IgnoreOnIsolate=yes +DefaultDependencies=no +After=basic\&.target +Conflicts=reboot\&.target +Before=reboot\&.target +Conflicts=kexec\&.target +Before=kexec\&.target +Conflicts=poweroff\&.target +Before=poweroff\&.target +Conflicts=halt\&.target +Before=halt\&.target +Conflicts=rescue\&.target +Before=rescue\&.target +Conflicts=emergency\&.target +Before=emergency\&.target + +[Service] +Type=oneshot +ExecStart=sleep infinity + +.fi +.if n \{\ +.RE +.\} .RE .sp .RS 4 @@ -226,11 +263,255 @@ File system mounts may remain mounted during the transition, and complex storage \fIDefaultDependencies=no\fR, and by avoiding \fIConflicts=umount\&.target\fR) .RE +.sp +.RS 4 +.ie n \{\ +\h'-04'\(bu\h'+03'\c +.\} +.el \{\ +.sp -1 +.IP \(bu 2.3 +.\} +If the unit publishes a service over D\-Bus, the connection needs to be re\-established after soft\-reboot as the D\-Bus broker will be stopped and then started again\&. When using the sd\-bus library this can be achieved by adapting the following example\&. +.sp +.if n \{\ +.RS 4 +.\} +.nf +/* SPDX\-License\-Identifier: MIT\-0 */ + +/* Implements a D\-Bus service that automatically reconnects when the system bus is restarted\&. + * + * Compile with \*(Aqcc sd_bus_service_reconnect\&.c $(pkg\-config \-\-libs \-\-cflags libsystemd)\*(Aq + * + * To allow the program to take ownership of the name \*(Aqorg\&.freedesktop\&.ReconnectExample\*(Aq, + * add the following as /etc/dbus\-1/system\&.d/org\&.freedesktop\&.ReconnectExample\&.conf + * and then reload the broker with \*(Aqsystemctl reload dbus\*(Aq: + +<?xml version="1\&.0"?> <!\-\-*\-nxml\-*\-\-> +<!DOCTYPE busconfig PUBLIC "\-//freedesktop//DTD D\-BUS Bus Configuration 1\&.0//EN" + "http://www\&.freedesktop\&.org/standards/dbus/1\&.0/busconfig\&.dtd"> +<busconfig> + <policy user="root"> + <allow own="org\&.freedesktop\&.ReconnectExample"/> + <allow send_destination="org\&.freedesktop\&.ReconnectExample"/> + <allow receive_sender="org\&.freedesktop\&.ReconnectExample"/> + </policy> + + <policy context="default"> + <allow send_destination="org\&.freedesktop\&.ReconnectExample"/> + <allow receive_sender="org\&.freedesktop\&.ReconnectExample"/> + </policy> +</busconfig> + + * + * To get the property via busctl: + * + * $ busctl \-\-user get\-property org\&.freedesktop\&.ReconnectExample \e + * /org/freedesktop/ReconnectExample \e + * org\&.freedesktop\&.ReconnectExample \e + * Example + * s "example" + */ + +#include <errno\&.h> +#include <stdio\&.h> +#include <stdlib\&.h> +#include <systemd/sd\-bus\&.h> + +#define _cleanup_(f) __attribute__((cleanup(f))) + +#define check(x) ({ \e + int _r = (x); \e + errno = _r < 0 ? \-_r : 0; \e + printf(#x ": %m\en"); \e + if (_r < 0) \e + return EXIT_FAILURE; \e + }) + +typedef struct object { + const char *example; + sd_bus **bus; + sd_event **event; +} object; + +static int property_get( + sd_bus *bus, + const char *path, + const char *interface, + const char *property, + sd_bus_message *reply, + void *userdata, + sd_bus_error *error) { + + object *o = userdata; + + if (strcmp(property, "Example") == 0) + return sd_bus_message_append(reply, "s", o\->example); + + return sd_bus_error_setf(error, + SD_BUS_ERROR_UNKNOWN_PROPERTY, + "Unknown property \*(Aq%s\*(Aq", + property); +} + +/* https://www\&.freedesktop\&.org/software/systemd/man/sd_bus_add_object\&.html */ +static const sd_bus_vtable vtable[] = { + SD_BUS_VTABLE_START(0), + SD_BUS_PROPERTY( + "Example", "s", + property_get, + 0, + SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_VTABLE_END +}; + +static int setup(object *o); + +static int on_disconnect(sd_bus_message *message, void *userdata, sd_bus_error *ret_error) { + check(setup((object *)userdata)); + return 0; +} + +/* Ensure the event loop exits with a clear error if acquiring the well\-known service name fails */ +static int request_name_callback(sd_bus_message *m, void *userdata, sd_bus_error *ret_error) { + if (!sd_bus_message_is_method_error(m, NULL)) + return 1; + + const sd_bus_error *error = sd_bus_message_get_error(m); + + if (sd_bus_error_has_names(error, SD_BUS_ERROR_TIMEOUT, SD_BUS_ERROR_NO_REPLY)) + return 1; /* The bus is not available, try again later */ + + printf("Failed to request name: %s\en", error\->message); + object *o = userdata; + check(sd_event_exit(*o\->event, \-sd_bus_error_get_errno(error))); + + return 1; +} + +static int setup(object *o) { + /* If we are reconnecting, then the bus object needs to be closed, detached from + * the event loop and recreated\&. + * https://www\&.freedesktop\&.org/software/systemd/man/sd_bus_detach_event\&.html + * https://www\&.freedesktop\&.org/software/systemd/man/sd_bus_close_unref\&.html + */ + if (*o\->bus) { + check(sd_bus_detach_event(*o\->bus)); + *o\->bus = sd_bus_close_unref(*o\->bus); + } + + /* Set up a new bus object for the system bus, configure it to wait for D\-Bus to be available + * instead of failing if it is not, and start it\&. All the following operations are asyncronous + * and will not block waiting for D\-Bus to be available\&. + * https://www\&.freedesktop\&.org/software/systemd/man/sd_bus_new\&.html + * https://www\&.freedesktop\&.org/software/systemd/man/sd_bus_set_address\&.html + * https://www\&.freedesktop\&.org/software/systemd/man/sd_bus_set_bus_client\&.html + * https://www\&.freedesktop\&.org/software/systemd/man/sd_bus_negotiate_creds\&.html + * https://www\&.freedesktop\&.org/software/systemd/man/sd_bus_set_watch_bind\&.html + * https://www\&.freedesktop\&.org/software/systemd/man/sd_bus_set_connected_signal\&.html + * https://www\&.freedesktop\&.org/software/systemd/man/sd_bus_start\&.html + */ + check(sd_bus_new(o\->bus)); + check(sd_bus_set_address(*o\->bus, "unix:path=/run/dbus/system_bus_socket")); + check(sd_bus_set_bus_client(*o\->bus, 1)); + check(sd_bus_negotiate_creds(*o\->bus, 1, SD_BUS_CREDS_UID|SD_BUS_CREDS_EUID|SD_BUS_CREDS_EFFECTIVE_CAPS)); + check(sd_bus_set_watch_bind(*o\->bus, 1)); + check(sd_bus_start(*o\->bus)); + + /* Publish an interface on the bus, specifying our well\-known object access + * path and public interface name\&. + * https://www\&.freedesktop\&.org/software/systemd/man/sd_bus_add_object\&.html + * https://dbus\&.freedesktop\&.org/doc/dbus\-tutorial\&.html + */ + check(sd_bus_add_object_vtable(*o\->bus, + NULL, + "/org/freedesktop/ReconnectExample", + "org\&.freedesktop\&.ReconnectExample", + vtable, + o)); + /* By default the service is only assigned an ephemeral name\&. Also add a well\-known + * one, so that clients know whom to call\&. This needs to be asynchronous, as + * D\-Bus might not be yet available\&. The callback will check whether the error is + * expected or not, in case it fails\&. + * https://www\&.freedesktop\&.org/software/systemd/man/sd_bus_request_name\&.html + */ + check(sd_bus_request_name_async(*o\->bus, + NULL, + "org\&.freedesktop\&.ReconnectExample", + 0, + request_name_callback, + o)); + /* When D\-Bus is disconnected this callback will be invoked, which will + * set up the connection again\&. This needs to be asynchronous, as D\-Bus might not + * yet be available\&. + * https://www\&.freedesktop\&.org/software/systemd/man/sd_bus_match_signal_async\&.html + */ + check(sd_bus_match_signal_async(*o\->bus, + NULL, + "org\&.freedesktop\&.DBus\&.Local", + NULL, + "org\&.freedesktop\&.DBus\&.Local", + "Disconnected", + on_disconnect, + NULL, + o)); + /* Attach the bus object to the event loop so that calls and signals are processed\&. + * https://www\&.freedesktop\&.org/software/systemd/man/sd_bus_attach_event\&.html + */ + check(sd_bus_attach_event(*o\->bus, *o\->event, 0)); + + return 0; +} + +int main(int argc, char **argv) { + /* The bus should be relinquished before the program terminates\&. The cleanup + * attribute allows us to do it nicely and cleanly whenever we exit the + * block\&. + */ + _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL; + _cleanup_(sd_event_unrefp) sd_event *event = NULL; + object o = { + \&.example = "example", + \&.bus = &bus, + \&.event = &event, + }; + + /* Create an event loop data structure, with default parameters\&. + * https://www\&.freedesktop\&.org/software/systemd/man/sd_event_default\&.html + */ + check(sd_event_default(&event)); + + /* By default the event loop will terminate when all sources have disappeared, so + * we have to keep it \*(Aqoccupied\*(Aq\&. Register signal handling to do so\&. + * https://www\&.freedesktop\&.org/software/systemd/man/sd_event_add_signal\&.html + */ + check(sd_event_add_signal(event, NULL, SIGINT|SD_EVENT_SIGNAL_PROCMASK, NULL, NULL)); + check(sd_event_add_signal(event, NULL, SIGTERM|SD_EVENT_SIGNAL_PROCMASK, NULL, NULL)); + + check(setup(&o)); + + /* Enter the main loop, it will exit only on sigint/sigterm\&. + * https://www\&.freedesktop\&.org/software/systemd/man/sd_event_loop\&.html + */ + check(sd_event_loop(event)); + + /* https://www\&.freedesktop\&.org/software/systemd/man/sd_bus_release_name\&.html */ + check(sd_bus_release_name(bus, "org\&.freedesktop\&.ReconnectExample")); + + return 0; +} +.fi +.if n \{\ +.RE +.\} +.sp +.RE .PP Even though passing resources from one soft reboot cycle to the next is possible this way, we strongly suggest to use this functionality sparingly only, as it creates a more fragile system as resources from different versions of the OS and applications might be mixed with unforeseen consequences\&. In particular it\*(Aqs recommended to \fIavoid\fR allowing processes to survive the soft reboot operation, as this means code updates will necessarily be incomplete, and processes typically pin various other resources (such as the file system they are backed by), thus increasing memory usage (as two versions of the OS/application/file system might be kept in memory)\&. Leaving processes running during a soft\-reboot operation requires disconnecting the service comprehensively from the rest of the OS, i\&.e\&. minimizing IPC and reducing sharing of resources with the rest of the OS\&. A possible mechanism to achieve this is the concept of -\m[blue]\fBPortable Services\fR\m[]\&\s-2\u[2]\d\s+2, but make sure no resource from the host\*(Aqs OS filesystems is pinned via +\m[blue]\fBPortable Services\fR\m[]\&\s-2\u[1]\d\s+2, but make sure no resource from the host\*(Aqs OS filesystems is pinned via \fIBindPaths=\fR or similar unit settings, otherwise the old, originating filesystem will remain mounted as long as the unit is running\&. .SH "NOTES" @@ -245,6 +526,13 @@ Note that systemd\-soft\-reboot\&.service (and related units) should never be executed directly\&. Instead, trigger system shutdown with a command such as "systemctl soft\-reboot"\&. +.PP +Note that if a new root file system has been set up on +"/run/nextroot/", a +\fBsoft\-reboot\fR +will be performed when the +\fBreboot\fR +command is invoked\&. .SH "SEE ALSO" .PP \fBsystemd\fR(1), @@ -255,11 +543,6 @@ systemd\-soft\-reboot\&.service \fBbootup\fR(7) .SH "NOTES" .IP " 1." 4 -systemd and Storage Daemons for the Root File System -.RS 4 -\%https://systemd.io/ROOT_STORAGE_DAEMONS -.RE -.IP " 2." 4 Portable Services .RS 4 \%https://systemd.io/PORTABLE_SERVICES |