packaging: restart imsd and imsd-ofonod on upgrade
An upgrade left the old imsd and imsd-ofonod running until they were
next restarted, while a changed bus policy is live the moment apk writes
it: dbus-broker-launch reloads on its own. A policy that relies on a
check inside the daemons would face the old daemons in between.
Mark imsd.service and imsd-ofonod.service needs-restart in post-upgrade
scripts; the systemd trigger restarts them once the transaction is done
(enqueue-marked). A call in progress ends. The same scripts run as
post-install: `apk del` removes a package's files and leaves its daemon
running, so a later `apk add` of the package is this upgrade for that
daemon — and apk runs the post-install script, not post-upgrade, for a
package it adds. GNOME Calls 50.0 dials nothing after imsd-ofonod
restarts under it until it restarts too, so imsd-ofonod's ExecStartPost
restarts the Calls daemon of each user running one — not at the unit's
first start since boot, when a Calls that runs already is left alone.
A daemon older than 0.3.10 kept its bring-up throttle wait in memory
only, so a restart lost it. imsd's post-upgrade records that daemon's
invocation, and imsd-handover.sh, an ExecStartPre after ims-pdn-up.sh,
reads the invocation's journal and, while the fresh-SA throttle's wait
it finds there still runs (`spi-s=0`; the old daemon's other deferrals
are not handed over), writes what is left of it to the holds file when
this start's LOCAL is the address the wait was earned on, or when that
address cannot be read; when LOCAL is another address, only the verdict
that the old registration is gone.
Tested on the dev phone (KPN) in builds of this series; not every path
has run there.
2026-10-04 00:09:37 +02:00
|
|
|
#!/bin/sh
|
|
|
|
|
# SPDX-License-Identifier: GPL-3.0-only
|
|
|
|
|
# SPDX-FileCopyrightText: Copyright (C) 2026 Catcrafts®
|
|
|
|
|
#
|
|
|
|
|
# Restart imsd onto the upgraded binary once apk is done: the systemd
|
|
|
|
|
# trigger restarts every unit marked needs-restart (enqueue-marked). A
|
|
|
|
|
# changed bus policy is live the moment apk writes it (dbus-broker-launch
|
|
|
|
|
# reloads on its own), so it must not be left facing the old daemon. The
|
ipsec, imsd, ims-pdn-up: the SA reader and the holds key compare in canonical form; LOCAL is canonicalised, PCSCF= accepted in RFC 5952 §4 form only
ParseExistingSa and SaLocals compared PCSCF= and LOCAL= as text against
`ip xfrm` output, which prints RFC 5952 form, so an upper-case or
uncompressed PCSCF= found no SAs and the restart registered fresh — on
KPN into the live-SA refusal; the holds file's pdn key compared the same
way. Both sides of each of those compares now go through
imsd::util::CanonicalAddr, LOCAL is canonicalised once on the way in, and PCSCF= is accepted in
that one spelling only — upper case, leading zeros or an uncompressed run
are refused at bring-up with the spelling to use, a dotted-quad tail (the
form ip prints for an IPv4-mapped address, which CanonicalIp6 does not read)
with the rule alone, a bracketed one by the bring-up script, which routes
the value as typed, with the rule (no brackets) — and a comma-separated
PCSCF= (a list) with its own message instead of reaching the socket layer: one spelling,
instead of a leniency both consumers of the setting would have to share.
Tested: crafter-build test, 7 passed; the upper-case PCSCF= refused with the spelling to use, a bracketed one
refused by the script, and the spelling they name resuming, in builds of
this series on the dev phone (KPN).
2026-10-11 15:55:19 +02:00
|
|
|
# restart resumes the registration over its existing SAs, goes on waiting
|
|
|
|
|
# when the network had imsd wait, or — an upper-case, zero-padded or uncompressed PCSCF=,
|
|
|
|
|
# accepted until 0.3.12 — stops at bring-up with the spelling to use; a
|
|
|
|
|
# call in progress ends.
|
packaging: restart imsd and imsd-ofonod on upgrade
An upgrade left the old imsd and imsd-ofonod running until they were
next restarted, while a changed bus policy is live the moment apk writes
it: dbus-broker-launch reloads on its own. A policy that relies on a
check inside the daemons would face the old daemons in between.
Mark imsd.service and imsd-ofonod.service needs-restart in post-upgrade
scripts; the systemd trigger restarts them once the transaction is done
(enqueue-marked). A call in progress ends. The same scripts run as
post-install: `apk del` removes a package's files and leaves its daemon
running, so a later `apk add` of the package is this upgrade for that
daemon — and apk runs the post-install script, not post-upgrade, for a
package it adds. GNOME Calls 50.0 dials nothing after imsd-ofonod
restarts under it until it restarts too, so imsd-ofonod's ExecStartPost
restarts the Calls daemon of each user running one — not at the unit's
first start since boot, when a Calls that runs already is left alone.
A daemon older than 0.3.10 kept its bring-up throttle wait in memory
only, so a restart lost it. imsd's post-upgrade records that daemon's
invocation, and imsd-handover.sh, an ExecStartPre after ims-pdn-up.sh,
reads the invocation's journal and, while the fresh-SA throttle's wait
it finds there still runs (`spi-s=0`; the old daemon's other deferrals
are not handed over), writes what is left of it to the holds file when
this start's LOCAL is the address the wait was earned on, or when that
address cannot be read; when LOCAL is another address, only the verdict
that the old registration is gone.
Tested on the dev phone (KPN) in builds of this series; not every path
has run there.
2026-10-04 00:09:37 +02:00
|
|
|
#
|
|
|
|
|
# Also installed as imsd.post-install: `apk del imsd` removes the files
|
|
|
|
|
# and leaves the daemon running, so a later `apk add` of the package is
|
|
|
|
|
# this upgrade for that daemon, and apk runs post-install for it. A first
|
|
|
|
|
# install finds no unit active and marks nothing. On the binary route
|
|
|
|
|
# (APKBUILD.binary) the unit file ships in imsd-systemd, installed after
|
|
|
|
|
# this package; its imsd-systemd.post-upgrade marks the unit then.
|
|
|
|
|
#
|
|
|
|
|
# A daemon older than 0.3.10 kept its bring-up throttle wait in memory
|
|
|
|
|
# only, so a restart inside it registered fresh at once instead of
|
|
|
|
|
# waiting the schedule out. Before marking, record the running
|
|
|
|
|
# invocation in /run/imsd.handover: the next start (imsd-handover.sh, an
|
|
|
|
|
# ExecStartPre after ims-pdn-up.sh) reads that invocation's last bring-up
|
|
|
|
|
# line once the daemon has stopped and hands what is left of its wait over
|
|
|
|
|
# as imsd's holds file (on another address only the verdict that its
|
|
|
|
|
# registration is gone). Read then, not here: a wait that ends between this
|
|
|
|
|
# script and the restart at the end of the transaction — the old daemon
|
|
|
|
|
# making another attempt — is read as it ended.
|
|
|
|
|
|
|
|
|
|
# A unit whose file an apk del removed is not-found to systemd until a
|
|
|
|
|
# reload and refuses properties ("failed to load properly"); its file is
|
|
|
|
|
# back on disk by the time post-install runs, so reload and mark again.
|
|
|
|
|
mark() {
|
|
|
|
|
systemctl set-property "$1" Markers=+needs-restart 2>/dev/null && return 0
|
|
|
|
|
systemctl daemon-reload && systemctl set-property "$1" Markers=+needs-restart || :
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
record_old_invocation() {
|
|
|
|
|
[ -e /run/imsd.holds ] && return 0 # a 0.3.10 or later daemon keeps its own holds
|
|
|
|
|
inv=$(systemctl show -P InvocationID imsd.service 2>/dev/null)
|
|
|
|
|
[ -n "$inv" ] && echo "$inv" > /run/imsd.handover
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if [ -d /run/systemd/system ] && systemctl is-active -q imsd.service; then
|
|
|
|
|
record_old_invocation
|
|
|
|
|
mark imsd.service
|
|
|
|
|
fi
|
|
|
|
|
exit 0
|