Say an update is running before it starts, not only after
Asked what happens if someone shuts the laptop down mid-update, the honest answer turned out to be poor. The inhibitor does stop them - logind refuses and falls back to org.freedesktop.login1.power-off-ignore-inhibit, which is auth_admin_keep - so the desktop answers with an administrator password prompt reading "Power off the system while an application is inhibiting this". systemd ships that string untranslated, it never mentions updates, and no KDE catalog contains any shutdown-blocked text at all. Only systemctl names the reason. So a notification now goes out before the transaction, asking for the machine to be left on. Notifications gained a tag: the result replaces the start message in place rather than stacking a second, contradictory bubble beside it. Tagged notifications also carry a queue flag. "An update is starting" is only meaningful while somebody is looking, so unlike the result it is not spooled for delivery at next login.
This commit is contained in:
1 parent
0f91a79ba6
commit
2eff62f9fd
10 files changed
+94
-11
No files matched your search
@@ -8,7 +8,7 @@
|
||||
# Overridable so a packager can pass the version it is actually building
|
||||
# (`make VERSION=$pkgver`). The literal below is the fallback for builds
|
||||
# straight from a checkout, and is what a release tag has to carry.
|
||||
VERSION ?= 1.0.8
|
||||
VERSION ?= 1.0.9
|
||||
|
||||
PREFIX ?= /usr
|
||||
DESTDIR ?=
|
||||
|
||||
@@ -127,10 +127,22 @@ unheld on several consecutive runs, you get a notification instead.
|
||||
|
||||
Three layers, in order of how much they can actually promise:
|
||||
|
||||
**A notification goes out before the transaction starts** — "Installing
|
||||
updates, please leave the computer switched on until this is done" — and is
|
||||
replaced in place by the result when the run finishes, so it costs one bubble
|
||||
rather than two. This exists because of what the next paragraph does *not* do.
|
||||
|
||||
**Suspend and a normal shutdown are blocked.** The run holds a
|
||||
`systemd-inhibit --what=sleep:shutdown --mode=block` lock, so closing the lid,
|
||||
picking "Shut down" from the menu or a short press of the power button will not
|
||||
interrupt a transaction — the desktop says something is still busy instead.
|
||||
`systemd-inhibit --what=sleep:shutdown --mode=block` lock, so closing the lid or
|
||||
picking "Shut down" cannot interrupt a transaction. Be aware of what that looks
|
||||
like, though: logind refuses the request and requires the polkit action
|
||||
`org.freedesktop.login1.power-off-ignore-inhibit`, which is `auth_admin_keep`.
|
||||
The desktop therefore answers a shutdown attempt with an **administrator
|
||||
password prompt** reading *"Power off the system while an application is
|
||||
inhibiting this"* — a string systemd ships untranslated, and one that never
|
||||
mentions updates. No KDE dialog explains the situation. Only `systemctl
|
||||
poweroff` in a terminal names the reason. That prompt is exactly why the
|
||||
notification above is on by default.
|
||||
|
||||
**A hard power-off cannot be prevented by anything.** Holding the power button
|
||||
or pulling the plug cuts power in firmware. What limits the damage is that
|
||||
|
||||
@@ -102,10 +102,23 @@ restart necessary, a notification says so.
|
||||
|
||||
# INTERRUPTED UPDATES
|
||||
|
||||
Before a transaction starts, a notification says an update is running and asks
|
||||
for the machine to be left on. It is replaced in place by the result once the
|
||||
run finishes.
|
||||
|
||||
While a transaction is running, *cachy-auto-update* holds a
|
||||
*systemd-inhibit*(1) lock on _sleep_ and _shutdown_ in blocking mode, so a
|
||||
suspend, a lid close or a normal shutdown request cannot cut it short.
|
||||
|
||||
What a user sees when they try anyway is worth knowing: logind refuses the
|
||||
request and falls back to the polkit action
|
||||
_org.freedesktop.login1.power-off-ignore-inhibit_, which is _auth_admin_keep_,
|
||||
so the desktop presents an administrator password prompt reading "Power off the
|
||||
system while an application is inhibiting this". That string is shipped
|
||||
untranslated by systemd and does not mention updates, and no KDE dialog
|
||||
explains the situation either - only *systemctl*(1) names the inhibitor and its
|
||||
reason. Hence the notification.
|
||||
|
||||
A hard power-off - holding the power button, or losing mains power - is not
|
||||
preventable. On the next run a leftover _/var/lib/pacman/db.lck_ is removed if
|
||||
it is older than the current boot, since no process able to hold it can still
|
||||
|
||||
@@ -263,3 +263,9 @@ msgstr ""
|
||||
|
||||
msgid "The last update was cut short, most likely because the machine was switched off. It is being finished now."
|
||||
msgstr ""
|
||||
|
||||
msgid "Installing updates"
|
||||
msgstr ""
|
||||
|
||||
msgid "%d packages are being updated. Please leave the computer switched on until this is done."
|
||||
msgstr ""
|
||||
@@ -264,3 +264,10 @@ msgstr "Abgebrochenes Update wird beendet"
|
||||
|
||||
msgid "The last update was cut short, most likely because the machine was switched off. It is being finished now."
|
||||
msgstr "Das letzte Update wurde unterbrochen, vermutlich weil der Rechner ausgeschaltet wurde. Es wird jetzt zu Ende geführt."
|
||||
|
||||
msgid "Installing updates"
|
||||
msgstr "Updates werden installiert"
|
||||
|
||||
#, c-format
|
||||
msgid "%d packages are being updated. Please leave the computer switched on until this is done."
|
||||
msgstr "%d Pakete werden gerade aktualisiert. Bitte den Rechner so lange eingeschaltet lassen."
|
||||
@@ -95,6 +95,12 @@ RemoveOrphans=no
|
||||
# Notification detail
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
# Say that an update has started. Worth keeping on: while one runs, a shutdown
|
||||
# request is refused and the desktop answers with an untranslated polkit
|
||||
# password prompt that never mentions updates. This message is replaced by the
|
||||
# result when the run finishes, so it costs one bubble, not two.
|
||||
NotifyOnStart=yes
|
||||
|
||||
# Say something after a successful update. Nothing is ever shown when there
|
||||
# was nothing to do.
|
||||
NotifyOnSuccess=yes
|
||||
|
||||
@@ -213,7 +213,7 @@ cau_state_write last_counts \
|
||||
if (( failed )); then
|
||||
cau_state_write last_result failed
|
||||
cau_error "Update run finished with errors"
|
||||
[[ $CFG_NOTIFY_ERROR == yes ]] && cau_notify critical \
|
||||
[[ $CFG_NOTIFY_ERROR == yes ]] && cau_notify_tagged run yes critical \
|
||||
"Update failed" \
|
||||
"Something went wrong while updating. Run 'cachy-auto-update log' for details."
|
||||
else
|
||||
@@ -222,7 +222,7 @@ else
|
||||
cau_info "Update run finished successfully ($total item(s) updated)"
|
||||
|
||||
if (( total > 0 )) && [[ $CFG_NOTIFY_SUCCESS == yes ]]; then
|
||||
cau_notify low "System updated" "%d updates were installed." "$total"
|
||||
cau_notify_tagged run yes low "System updated" "%d updates were installed." "$total"
|
||||
fi
|
||||
fi
|
||||
|
||||
|
||||
@@ -98,6 +98,7 @@ cau_config_load() {
|
||||
CFG_RESOLVE_CONFLICTS=no; cau_config_bool AutoResolveConflicts yes && CFG_RESOLVE_CONFLICTS=yes
|
||||
CFG_CLEAN_CACHE=no; cau_config_bool CleanCache yes && CFG_CLEAN_CACHE=yes
|
||||
CFG_REMOVE_ORPHANS=no; cau_config_bool RemoveOrphans no && CFG_REMOVE_ORPHANS=yes
|
||||
CFG_NOTIFY_START=no; cau_config_bool NotifyOnStart yes && CFG_NOTIFY_START=yes
|
||||
CFG_NOTIFY_SUCCESS=no; cau_config_bool NotifyOnSuccess yes && CFG_NOTIFY_SUCCESS=yes
|
||||
CFG_NOTIFY_ERROR=no; cau_config_bool NotifyOnError yes && CFG_NOTIFY_ERROR=yes
|
||||
CFG_NOTIFY_REBOOT=no; cau_config_bool NotifyReboot yes && CFG_NOTIFY_REBOOT=yes
|
||||
|
||||
+29
-5
@@ -19,10 +19,23 @@ CAU_NOTIFY_QUEUE_MAX=20
|
||||
# Never fails: a machine without libnotify, or with nobody logged in, is a
|
||||
# normal state, not an error.
|
||||
cau_notify() {
|
||||
local urgency="$1" title="$2" body="$3"
|
||||
shift 3
|
||||
cau_notify_tagged '' yes "$@"
|
||||
}
|
||||
|
||||
# cau_notify_tagged <tag> <queue: yes|no> <urgency> <title> <body> [args...]
|
||||
#
|
||||
# A tag makes this notification replace the previous one carrying the same tag
|
||||
# rather than stacking a second bubble beside it - that is what turns
|
||||
# "installing updates" into "system updated" in place instead of leaving two
|
||||
# messages that contradict each other.
|
||||
#
|
||||
# queue=no is for messages that only mean anything while somebody is looking.
|
||||
# Telling a user at next login that an update started an hour ago is noise.
|
||||
cau_notify_tagged() {
|
||||
local tag="$1" queue="$2" urgency="$3" title="$4" body="$5"
|
||||
shift 5
|
||||
local -a args=("$@")
|
||||
local delivered=0 user uid locale t b
|
||||
local delivered=0 user uid locale t b prev newid
|
||||
|
||||
[[ $CFG_NOTIFICATIONS == yes ]] || return 0
|
||||
|
||||
@@ -34,17 +47,28 @@ cau_notify() {
|
||||
t="$(cau_msg_in "$locale" "$title")"
|
||||
b="$(cau_msg_in "$locale" "$body" "${args[@]}")"
|
||||
|
||||
if cau_as_user "$user" "$uid" notify-send \
|
||||
prev=0
|
||||
if [[ -n $tag ]]; then
|
||||
prev="$(cau_state_read "notify_id_${tag}_${user}" 0)"
|
||||
[[ $prev =~ ^[0-9]+$ ]] || prev=0
|
||||
fi
|
||||
|
||||
if newid="$(cau_as_user "$user" "$uid" notify-send \
|
||||
--app-name="$CAU_PRETTY" \
|
||||
--icon="$CAU_NOTIFY_ICON" \
|
||||
--urgency="$urgency" \
|
||||
-- "$t" "$b" 2>/dev/null
|
||||
--print-id --replace-id="$prev" \
|
||||
-- "$t" "$b" 2>/dev/null)"
|
||||
then
|
||||
delivered=1
|
||||
if [[ -n $tag && $newid =~ ^[0-9]+$ ]]; then
|
||||
cau_state_write "notify_id_${tag}_${user}" "$newid"
|
||||
fi
|
||||
fi
|
||||
done < <(cau_active_session_users)
|
||||
|
||||
(( delivered )) && return 0
|
||||
[[ $queue == yes ]] || return 0
|
||||
|
||||
cau_notify_enqueue "$urgency" "$title" "$body" "${args[@]}"
|
||||
}
|
||||
|
||||
@@ -133,6 +133,20 @@ cau_pacman_update() {
|
||||
cau_info "Running a full system upgrade (pending list unavailable)"
|
||||
fi
|
||||
|
||||
# Say so before the transaction starts, not after it finishes.
|
||||
#
|
||||
# While an upgrade runs, a shutdown request is refused by logind and the
|
||||
# desktop answers with a polkit password prompt reading "Power off the
|
||||
# system while an application is inhibiting this" - which never mentions
|
||||
# updates and, on a German system, is not even translated. Somebody who was
|
||||
# simply told beforehand does not end up staring at that.
|
||||
if [[ $CFG_NOTIFY_START == yes ]]; then
|
||||
cau_notify_tagged run no normal \
|
||||
"Installing updates" \
|
||||
"%d packages are being updated. Please leave the computer switched on until this is done." \
|
||||
"${CAU_PACMAN_COUNT:-0}"
|
||||
fi
|
||||
|
||||
mapfile -t flags < <(cau_pacman_flags)
|
||||
log="$(mktemp)" || return 1
|
||||
|
||||
|
||||
Reference in new issue
Block a user