From a18c43267b57399040f6adc8d846edcc19fc759f Mon Sep 17 00:00:00 2001 From: decay71 <119651599+decay71@users.noreply.github.com> Date: Sat, 10 Oct 2026 10:59:52 +0000 Subject: [PATCH] multiACE 1.27b Updater: the install replaces multiace_update.sh by rename and the updater's dispatch is parsed before it runs, so a running update no longer reads its own replaced file (the "shift count out of range" / "syntax error near ';;'" lines after a successful update). --- multiace/VERSION | 2 +- multiace/install_multiace.sh | 30 ++++++++++++++-------- multiace/klipper/extras/ace.py | 4 +-- multiace/tools/multiace_update.sh | 42 +++++++++++++++++++------------ 4 files changed, 49 insertions(+), 29 deletions(-) diff --git a/multiace/VERSION b/multiace/VERSION index e766dac..33108a3 100644 --- a/multiace/VERSION +++ b/multiace/VERSION @@ -1 +1 @@ -1.26b +1.27b diff --git a/multiace/install_multiace.sh b/multiace/install_multiace.sh index 7cc025e..796c953 100755 --- a/multiace/install_multiace.sh +++ b/multiace/install_multiace.sh @@ -280,22 +280,32 @@ if [ -d "$INSTALL_DIR/tools" ]; then cp "$INSTALL_DIR/tools/"*.py "${HOME_DIR}/printer_data/config/tools/" 2>/dev/null || true log " Tools installed" fi +# The updater is usually the process RUNNING this installer (web update). +# bash reads a script while executing it, so overwriting that file in +# place (cp = same inode) makes the running copy continue in the new text +# at the old offset. A rename (new inode) leaves the running copy on its +# old file. Also protects updaters older than this fix. +install_updater_copy() { + _dst="$1" + _tmp="$_dst.new.$$" + cp "$INSTALL_DIR/tools/multiace_update.sh" "$_tmp" 2>/dev/null || return 1 + chmod 755 "$_tmp" 2>/dev/null || true + chown lava:lava "$_tmp" 2>/dev/null || true + mv -f "$_tmp" "$_dst" 2>/dev/null || { rm -f "$_tmp"; return 1; } + return 0 +} if [ -f "$INSTALL_DIR/tools/multiace_update.sh" ]; then mkdir -p "$MULTIACE_DIR/.." - cp "$INSTALL_DIR/tools/multiace_update.sh" "$HOME_DIR/multiace_update.sh" - chmod 755 "$HOME_DIR/multiace_update.sh" - chown lava:lava "$HOME_DIR/multiace_update.sh" 2>/dev/null || true - log " Updater installed at $HOME_DIR/multiace_update.sh" + install_updater_copy "$HOME_DIR/multiace_update.sh" \ + && log " Updater installed at $HOME_DIR/multiace_update.sh" \ + || log " WARN: could not install $HOME_DIR/multiace_update.sh" # PAXX-baked firmware ships a copy at /home/lava/multiace/tools/ # from the squashfs. Refresh it too so the Web backend's fallback # path doesn't lag behind the canonical one. if [ -d "$HOME_DIR/multiace/tools" ]; then - cp "$INSTALL_DIR/tools/multiace_update.sh" \ - "$HOME_DIR/multiace/tools/multiace_update.sh" 2>/dev/null && { - chmod 755 "$HOME_DIR/multiace/tools/multiace_update.sh" 2>/dev/null || true - chown lava:lava "$HOME_DIR/multiace/tools/multiace_update.sh" 2>/dev/null || true - log " Updater also refreshed at $HOME_DIR/multiace/tools/multiace_update.sh" - } || log " WARN: could not refresh $HOME_DIR/multiace/tools/multiace_update.sh" + install_updater_copy "$HOME_DIR/multiace/tools/multiace_update.sh" \ + && log " Updater also refreshed at $HOME_DIR/multiace/tools/multiace_update.sh" \ + || log " WARN: could not refresh $HOME_DIR/multiace/tools/multiace_update.sh" fi fi if [ -f "$INSTALL_DIR/tools/merge_ace_cfg.py" ]; then diff --git a/multiace/klipper/extras/ace.py b/multiace/klipper/extras/ace.py index a222c4b..e47c9a0 100644 --- a/multiace/klipper/extras/ace.py +++ b/multiace/klipper/extras/ace.py @@ -16,7 +16,7 @@ KNOWN_PROTOCOLS = (AceProtocolV1, AceProtocolV2) -MULTIACE_VERSION = "1.26b" +MULTIACE_VERSION = "1.27b" # Engine API contract version (see docs/ENGINE_API.md). Distinct from # MULTIACE_VERSION (the product version): this only bumps on a breaking @@ -24,7 +24,7 @@ # external host can detect engine capability. Additive changes do not bump it. ACE_API_VERSION = 1 -MULTIACE_BUILD_TAG = "8e027719" +MULTIACE_BUILD_TAG = "2725a008" MULTIACE_BUNDLE_SHA1 = "0f18123" # The former shipped value of [ace] update_url_base (static mirror); # read as unset so updates come from GitHub. diff --git a/multiace/tools/multiace_update.sh b/multiace/tools/multiace_update.sh index e601843..303b3ec 100644 --- a/multiace/tools/multiace_update.sh +++ b/multiace/tools/multiace_update.sh @@ -323,19 +323,29 @@ cmd_apply() { fi echo "STATUS: done from=$CUR to=$LATEST" } -case "${1:-check}" in - check) - shift; cmd_check "$@" ;; - assets) - shift; cmd_assets "$@" ;; - apply) - shift; cmd_apply "$@" ;; - -h|--help|help) - sed -n '/^# Usage:/,/^$/p' "$0" | sed 's/^#//; s/^ //' - ;; - *) - echo "ERROR: unknown command: $1" >&2 - echo "Run with --help for usage." >&2 - exit 2 - ;; -esac +# The apply path replaces THIS file (install_multiace.sh ships a new copy) +# while it is still running. bash reads a script as it executes it, so +# anything left to read after that point comes from the NEW file at the +# old byte offset (HW 2026-10-10: "shift count out of range", "syntax +# error near ';;'" after a successful 1.25b -> 1.26b update). Everything is +# therefore parsed into one function before it runs, and the last line is +# a single brace group, so nothing is read from disk after the dispatch. +main() { + case "${1:-check}" in + check) + shift; cmd_check "$@" ;; + assets) + shift; cmd_assets "$@" ;; + apply) + shift; cmd_apply "$@" ;; + -h|--help|help) + sed -n '/^# Usage:/,/^$/p' "$0" | sed 's/^#//; s/^ //' + ;; + *) + echo "ERROR: unknown command: $1" >&2 + echo "Run with --help for usage." >&2 + return 2 + ;; + esac +} +{ main "$@"; exit $?; }