Files
NeoTachyon/tachyon/Makefile
T
Dushnilin f770316345 fix: bound package hooks so apk cannot roll the upgrade back
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.
2026-08-09 18:23:16 +03:00

154 lines
5.5 KiB
Makefile

include $(TOPDIR)/rules.mk
PKG_NAME:=tachyon
TACHYON_SOURCE_VERSION:=$(or $(TACHYON_PACKAGE_VERSION),$(TACHYON_VERSION))
TACHYON_HAS_RELEASE_VERSION:=$(if $(filter dev,$(TACHYON_SOURCE_VERSION)),,$(TACHYON_SOURCE_VERSION))
TACHYON_COMPILED_VERSION:=$(if $(TACHYON_HAS_RELEASE_VERSION),$(TACHYON_SOURCE_VERSION),$(or $(TACHYON_SOURCE_VERSION),dev))
TACHYON_RELEASE_VERSION_VALID:=$(if $(TACHYON_HAS_RELEASE_VERSION),$(shell printf '%s\n' '$(TACHYON_SOURCE_VERSION)' | grep -Eq '^[0-9]+\.[0-9]+\.[0-9]+$$' && printf '1'),1)
ifeq ($(TACHYON_RELEASE_VERSION_VALID),)
$(error TACHYON_PACKAGE_VERSION and TACHYON_VERSION must use x.y.z format)
endif
PKG_VERSION:=$(or $(TACHYON_HAS_RELEASE_VERSION),0.0.0)
PKG_RELEASE:=
PKG_MAINTAINER:=Dushnilin <dushnilin@gmail.com>
PKG_LICENSE:=GPL-2.0-or-later
include $(INCLUDE_DIR)/package.mk
define Package/tachyon
SECTION:=net
CATEGORY:=Network
DEPENDS:=+ca-bundle +curl +ucode +ucode-mod-fs +ucode-mod-uci +coreutils-base64 +bind-dig +nftables +ip-full
CONFLICTS:=https-dns-proxy nextdns luci-app-passwall luci-app-passwall2
PROVIDES:=forkop
REPLACES:=forkop
TITLE:=Tachyon backend service
URL:=https://github.com/Dushnilin/tachyon
PKGARCH:=all
endef
define Package/tachyon/description
Rule-based Tachyon backend with hybrid sing-box + zapret orchestration
endef
define Build/Configure
endef
define Build/Compile
endef
define Package/tachyon/prerm
#!/usr/bin/ucode
// apk runs this as <pkg>-<version>.pre-upgrade and rolls the whole transaction
// back if the hook does not finish, which leaves the old build installed. The
// cleanup invoked below belongs to the OLD version, so it cannot be trusted to
// bound itself — the hook bounds it from the outside. 90s sits far below any
// package-manager or installer patience and far above a healthy cleanup.
// BusyBox timeout wanted `-t SECONDS` on older builds and rejects it on newer
// ones; the spelling is probed against /bin/true because probing with the real
// command would run the cleanup twice whenever the first form is unsupported.
if (getenv("IPKG_INSTROOT") == null || getenv("IPKG_INSTROOT") == "") {
let prefix = "";
if (system("timeout 1 /bin/true >/dev/null 2>&1") == 0)
prefix = "timeout 90 ";
else if (system("timeout -t 1 /bin/true >/dev/null 2>&1") == 0)
prefix = "timeout -t 90 ";
system(prefix + "/usr/bin/tachyon package_prerm >/dev/null 2>&1");
}
// Whatever the cleanup managed to do, the removal itself must proceed: a failing
// prerm aborts the upgrade on both package managers.
exit(0);
endef
define Package/tachyon/postupgrade
#!/bin/sh
[ -n "$${IPKG_INSTROOT}" ] && exit 0
# Kill everything that could hold or wait for the procd serialization lock
# (rc.common flock -w 1000). procd re-triggers retry_start_on_wan_up between
# pre-upgrade and post-upgrade, which continuously creates new flock waiters.
ps 2>/dev/null | grep -E '99-tachyon-wan|flock 1000' | awk '{print $$1}' | while read _pid; do
kill -9 "$$_pid" 2>/dev/null
done
ps 2>/dev/null | grep -F '/etc/init.d/tachyon' | awk '{print $$1}' | while read _pid; do
kill -9 "$$_pid" 2>/dev/null
done
# Start via tachyon binary (lifecycle.uc) which registers with procd directly,
# bypassing rc.common and its flock entirely.
/usr/bin/tachyon start >/dev/null 2>&1 || true
rm -f /var/run/tachyon/upgrade_state 2>/dev/null || true
chmod 600 /etc/config/tachyon 2>/dev/null || true
chown root:root /etc/config/tachyon 2>/dev/null || true
exit 0
endef
define Package/tachyon/postinst
#!/bin/sh
[ -n "$${IPKG_INSTROOT}" ] && exit 0
# Clean up legacy forkop package files
rm -rf /usr/lib/lua/luci/i18n/forkop.* /www/luci-static/resources/i18n/forkop.* \
/usr/share/luci/menu.d/luci-app-forkop.json /usr/share/rpcd/acl.d/luci-app-forkop.json \
/etc/uci-defaults/50_luci-forkop 2>/dev/null || true
# Migration from Forkop
if [ -f /etc/config/forkop ]; then
mv /etc/config/forkop /etc/config/tachyon
elif [ -f /etc/config/forkop_plus ]; then
mv /etc/config/forkop_plus /etc/config/tachyon
# Migration from Podkop
elif [ -f /etc/config/podkop ]; then
mv /etc/config/podkop /etc/config/tachyon
TACHYON_LIB=/usr/lib/tachyon ucode -L /usr/lib/tachyon /usr/lib/tachyon/config/migration.uc migrate-podkop
exit 0
elif [ -f /etc/config/podkop_plus ]; then
mv /etc/config/podkop_plus /etc/config/tachyon
TACHYON_LIB=/usr/lib/tachyon ucode -L /usr/lib/tachyon /usr/lib/tachyon/config/migration.uc migrate-podkop
exit 0
fi
TACHYON_LIB=/usr/lib/tachyon ucode -L /usr/lib/tachyon /usr/lib/tachyon/config/migration.uc migrate
/usr/bin/tachyon package_postinst
# Harden config: telegram bot_token must not be world-readable
chmod 600 /etc/config/tachyon
chown root:root /etc/config/tachyon
endef
define Package/tachyon/conffiles
/etc/config/tachyon
endef
define Package/tachyon/install
$(INSTALL_DIR) $(1)/etc/init.d
$(INSTALL_BIN) ./files/etc/init.d/tachyon $(1)/etc/init.d/tachyon
$(INSTALL_DIR) $(1)/etc/config
$(INSTALL_CONF) ./files/etc/config/tachyon $(1)/etc/config/tachyon
$(INSTALL_DIR) $(1)/usr/bin
$(INSTALL_BIN) ./files/usr/bin/tachyon $(1)/usr/bin/tachyon
$(INSTALL_DIR) $(1)/usr/lib/tachyon
$(CP) ./files/usr/lib/. $(1)/usr/lib/tachyon/
$(INSTALL_DIR) $(1)/etc/hotplug.d/iface
$(INSTALL_BIN) ./files/etc/hotplug.d/iface/99-tachyon-wan-monitor $(1)/etc/hotplug.d/iface/99-tachyon-wan-monitor
sed -i -e 's/__COMPILED_VERSION_VARIABLE__/$(TACHYON_COMPILED_VERSION)/g' \
-e 's/__COMPILED_COMMIT_SHA__/$(shell git -C $(TOPDIR)/../ rev-parse --short HEAD 2>/dev/null || echo unknown)/g' \
$(1)/usr/lib/tachyon/core/constants.uc
endef
$(eval $(call BuildPackage,tachyon))