mirror of
https://github.com/systemd/systemd.git
synced 2024-11-24 02:33:36 +08:00
logind: add PrepareForShutdownWithMetadata signal
The existing signal doesn't say which type of shutdown is going to happen. With the introduction of soft-reboot, it is useful to have this information broadcasted, so that clients can choose to do different things based on the reboot type. Add a{sv} as the payload so that more metadata can be added later if needed, without needing to add yet another signal. Send both old and new signal for backward compatibility, and send the new one first so that clients can just wait for the first one on both old and new systems.
This commit is contained in:
parent
fd0a804271
commit
e4aab5cf1a
@ -156,6 +156,8 @@ node /org/freedesktop/login1 {
|
||||
SeatRemoved(s seat_id,
|
||||
o object_path);
|
||||
PrepareForShutdown(b start);
|
||||
PrepareForShutdownWithMetadata(b start,
|
||||
a{sv} metadata);
|
||||
PrepareForSleep(b start);
|
||||
properties:
|
||||
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
|
||||
@ -402,6 +404,8 @@ node /org/freedesktop/login1 {
|
||||
|
||||
<variablelist class="dbus-signal" generated="True" extra-ref="PrepareForShutdown"/>
|
||||
|
||||
<variablelist class="dbus-signal" generated="True" extra-ref="PrepareForShutdownWithMetadata"/>
|
||||
|
||||
<variablelist class="dbus-signal" generated="True" extra-ref="PrepareForSleep"/>
|
||||
|
||||
<variablelist class="dbus-property" generated="True" extra-ref="EnableWallMessages"/>
|
||||
@ -674,15 +678,20 @@ node /org/freedesktop/login1 {
|
||||
logs in or out, or a seat is added or removed. They each contain the ID of the object plus the object
|
||||
path.</para>
|
||||
|
||||
<para>The <function>PrepareForShutdown()</function> and <function>PrepareForSleep()</function> signals
|
||||
are sent right before (with the argument <literal>true</literal>) or after (with the argument
|
||||
<para>The <function>PrepareForShutdown</function>,
|
||||
<function>PrepareForShutdownWithMetadata</function>, and <function>PrepareForSleep</function>
|
||||
signals are sent right before (with the argument <literal>true</literal>) or after (with the argument
|
||||
<literal>false</literal>) the system goes down for reboot/poweroff and suspend/hibernate,
|
||||
respectively. This may be used by applications to save data on disk, release memory, or do other jobs
|
||||
that should be done shortly before shutdown/sleep, in conjunction with delay inhibitor locks. After
|
||||
completion of this work they should release their inhibition locks in order to not delay the operation
|
||||
any further. For more information see
|
||||
<ulink url="https://www.freedesktop.org/wiki/Software/systemd/inhibit">Inhibitor Locks</ulink>.
|
||||
</para>
|
||||
<ulink url="https://www.freedesktop.org/wiki/Software/systemd/inhibit">Inhibitor Locks</ulink>. The
|
||||
<function>PrepareForShutdownWithMetadata()</function> signal additionally sends a list of key/value
|
||||
pair metadata fields. Currently it sends a <varname>type</varname> string which defines the type of
|
||||
shutdown. The type can be one of <literal>power-off</literal>, <literal>reboot</literal>,
|
||||
<literal>halt</literal>, <literal>kexec</literal> or <literal>soft-reboot</literal>. This signal is
|
||||
sent first, followed by <function>PrepareForShutdown</function> (for backward compatibility).</para>
|
||||
</refsect2>
|
||||
|
||||
<refsect2>
|
||||
|
@ -281,6 +281,8 @@ static const char* const handle_action_verb_table[_HANDLE_ACTION_MAX] = {
|
||||
|
||||
DEFINE_STRING_TABLE_LOOKUP_TO_STRING(handle_action_verb, HandleAction);
|
||||
|
||||
/* These strings are sent out by PrepareForShutdownWithMetadata signals as metadata, so the values cannot
|
||||
* change as they are public APIs. */
|
||||
static const char* const handle_action_table[_HANDLE_ACTION_MAX] = {
|
||||
[HANDLE_IGNORE] = "ignore",
|
||||
[HANDLE_POWEROFF] = "poweroff",
|
||||
|
@ -1548,18 +1548,43 @@ int manager_set_lid_switch_ignore(Manager *m, usec_t until) {
|
||||
return r;
|
||||
}
|
||||
|
||||
static int send_prepare_for(Manager *m, InhibitWhat w, bool _active) {
|
||||
int active = _active;
|
||||
static int send_prepare_for(Manager *m, const HandleActionData *a, bool _active) {
|
||||
int k = 0, r, active = _active;
|
||||
|
||||
assert(m);
|
||||
assert(IN_SET(w, INHIBIT_SHUTDOWN, INHIBIT_SLEEP));
|
||||
assert(a);
|
||||
assert(IN_SET(a->inhibit_what, INHIBIT_SHUTDOWN, INHIBIT_SLEEP));
|
||||
|
||||
return sd_bus_emit_signal(m->bus,
|
||||
"/org/freedesktop/login1",
|
||||
"org.freedesktop.login1.Manager",
|
||||
w == INHIBIT_SHUTDOWN ? "PrepareForShutdown" : "PrepareForSleep",
|
||||
"b",
|
||||
active);
|
||||
/* We need to send both old and new signal for backward compatibility. The newer one allows clients
|
||||
* to know which type of reboot is going to happen, as they might be doing different actions (e.g.:
|
||||
* on soft-reboot), and it is sent first, so that clients know that if they receive the old one
|
||||
* first then they don't have to wait for the new one, as it means it's not supported. So, do not
|
||||
* change the order here, as it is an API. */
|
||||
if (a->inhibit_what == INHIBIT_SHUTDOWN) {
|
||||
k = sd_bus_emit_signal(m->bus,
|
||||
"/org/freedesktop/login1",
|
||||
"org.freedesktop.login1.Manager",
|
||||
"PrepareForShutdownWithMetadata",
|
||||
"ba{sv}",
|
||||
active,
|
||||
1,
|
||||
"type",
|
||||
"s",
|
||||
handle_action_to_string(a->handle));
|
||||
if (k < 0)
|
||||
log_debug_errno(k, "Failed to emit PrepareForShutdownWithMetadata(): %m");
|
||||
}
|
||||
|
||||
r = sd_bus_emit_signal(m->bus,
|
||||
"/org/freedesktop/login1",
|
||||
"org.freedesktop.login1.Manager",
|
||||
a->inhibit_what == INHIBIT_SHUTDOWN ? "PrepareForShutdown" : "PrepareForSleep",
|
||||
"b",
|
||||
active);
|
||||
if (r < 0)
|
||||
log_debug_errno(r, "Failed to emit PrepareForShutdown(): %m");
|
||||
|
||||
return RET_GATHER(k, r);
|
||||
}
|
||||
|
||||
static int execute_shutdown_or_sleep(
|
||||
@ -1604,7 +1629,7 @@ static int execute_shutdown_or_sleep(
|
||||
|
||||
error:
|
||||
/* Tell people that they now may take a lock again */
|
||||
(void) send_prepare_for(m, a->inhibit_what, false);
|
||||
(void) send_prepare_for(m, a, false);
|
||||
|
||||
return r;
|
||||
}
|
||||
@ -1712,7 +1737,7 @@ int bus_manager_shutdown_or_sleep_now_or_later(
|
||||
a->target, load_state);
|
||||
|
||||
/* Tell everybody to prepare for shutdown/sleep */
|
||||
(void) send_prepare_for(m, a->inhibit_what, true);
|
||||
(void) send_prepare_for(m, a, true);
|
||||
|
||||
delayed =
|
||||
m->inhibit_delay_max > 0 &&
|
||||
@ -3708,6 +3733,9 @@ static const sd_bus_vtable manager_vtable[] = {
|
||||
SD_BUS_SIGNAL_WITH_ARGS("PrepareForShutdown",
|
||||
SD_BUS_ARGS("b", start),
|
||||
0),
|
||||
SD_BUS_SIGNAL_WITH_ARGS("PrepareForShutdownWithMetadata",
|
||||
SD_BUS_ARGS("b", start, "a{sv}", metadata),
|
||||
0),
|
||||
SD_BUS_SIGNAL_WITH_ARGS("PrepareForSleep",
|
||||
SD_BUS_ARGS("b", start),
|
||||
0),
|
||||
@ -3763,7 +3791,7 @@ int match_job_removed(sd_bus_message *message, void *userdata, sd_bus_error *err
|
||||
log_info("Operation '%s' finished.", inhibit_what_to_string(m->delayed_action->inhibit_what));
|
||||
|
||||
/* Tell people that they now may take a lock again */
|
||||
(void) send_prepare_for(m, m->delayed_action->inhibit_what, false);
|
||||
(void) send_prepare_for(m, m->delayed_action, false);
|
||||
|
||||
m->action_job = mfree(m->action_job);
|
||||
m->delayed_action = NULL;
|
||||
|
@ -76,6 +76,9 @@ elif [ -f /run/testsuite82.touch ]; then
|
||||
read -r x <&3
|
||||
test "$x" = "wuffwuff"
|
||||
|
||||
# Check that we got a PrepareForShutdownWithMetadata signal with the right type
|
||||
test "$(jq .payload.data[1].type.data </run/testsuite82.signal)" = "\"soft-reboot\""
|
||||
|
||||
# Upload another entry
|
||||
T="/dev/shm/fdstore.$RANDOM"
|
||||
echo "miaumiau" >"$T"
|
||||
@ -138,9 +141,17 @@ EOF
|
||||
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
|
||||
|
||||
# Check that we can set up an inhibitor, and that busctl monitor sees the
|
||||
# PrepareForShutdownWithMetadata signal and that it says 'soft-reboot'.
|
||||
systemd-run --unit busctl.service --property StandardOutput=file:/run/testsuite82.signal \
|
||||
busctl monitor --json=pretty --match 'sender=org.freedesktop.login1,path=/org/freedesktop/login1,interface=org.freedesktop.login1.Manager,member=PrepareForShutdownWithMetadata,type=signal'
|
||||
systemd-run --unit inhibit.service \
|
||||
systemd-inhibit --what=shutdown --who=test --why=test --mode=delay \
|
||||
sleep infinity
|
||||
|
||||
# Now issue the soft reboot. We should be right back soon.
|
||||
touch /run/testsuite82.touch
|
||||
systemctl --no-block soft-reboot
|
||||
systemctl --no-block --check-inhibitors=yes soft-reboot
|
||||
|
||||
# Now block until the soft-boot killing spree kills us
|
||||
exec sleep infinity
|
||||
|
Loading…
Reference in New Issue
Block a user