`ps | grep '/usr/bin/tachyon'` matches the hook itself, because
/usr/bin/tachyon is what invoked it. The sweep therefore killed its own
parent, the parent died on SIGKILL, and apk saw
`tachyon-<version>.pre-upgrade: exited with error 247` (128+119) and
reported a failed hook.
The sweep now walks /proc/<pid>/stat to collect its own ancestor chain and
skips those pids.
Holders of procd's serialization lock are also cleared by descriptor rather
than by name. procd_lock() does `exec 1000>` on
/var/lock/procd_tachyon.lock and then `flock 1000` with no -w, so any
background spawn inheriting fd 1000 keeps the lock held. On a live router
the holders were watchdog workers, logread, the zapret2 supervisors, nfqws2
and a stray curl — none of which match a tachyon name pattern. While any of
them lives, every init.d call blocks in flock until the package manager
gives up on the hook.
Same descriptor-based sweep added to install.sh, which faces the same lock
left behind by pre-fix builds.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
installed_backend_sha() rejects the unsubstituted __COMPILED_COMMIT_SHA__
placeholder and the literal "unknown", so a stale build on disk reports no SHA at
all. install_backend_package treated that empty value as "fresh install" and fell
through to the presence check, which passes trivially after an apk rollback — the
package and its version are still there. The run printed
WARN Package manager reported errors during installation, but tachyon is
installed — continuing
directly after the backend install had been rolled back, and then continued
through the remaining steps to a green banner over a failed upgrade.
Record whether tachyon was installed before the install and treat "was present,
still reports no SHA afterwards" as the failure it is. A genuine first install has
no package present beforehand and is unaffected.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Bounding the hooks fixes future upgrades, but the hook that runs during
THIS one belongs to the build already installed, and every release up to
1.2.66 shipped a prerm with no timeout. It blocks on rc.common's
flock -w 1000, which procd keeps re-populating with retry_start_on_wan_up
waiters between pre- and post-upgrade, so apk's pre-upgrade outlives its
patience and the transaction is rolled back.
cleanup_legacy already stops and disables the service; it now also kills
the flock waiters, so the old unbounded hook has nothing left to wait on.
The router upgrade died at the installer's 120s ceiling while apk was
running tachyon-1.2.66.pre-upgrade, so apk rolled the transaction back
and the old build stayed installed.
prerm reached INIT_PATH status through rc.common, which waits on
flock -w 1000. A stuck start or retry_start_on_wan_up holding that lock
stalls the hook for up to a quarter of an hour. Every init call in the
hooks is now bounded, the status probe moved after the flock waiters are
killed, and the Makefile hook bounds the old version's cleanup from the
outside since that code cannot be trusted to bound itself.
The installer also called a rollback a success: a rebuilt tag keeps its
version, so both the presence and version checks still passed. It now
compares the commit SHA baked into the installed constants module and
fails loudly when it did not move. Package installs get 300s, since a
kill mid-transaction is what caused the rollback.