diff --git a/MerlinAU.sh b/MerlinAU.sh index 5ddaf63..e5bd398 100644 --- a/MerlinAU.sh +++ b/MerlinAU.sh @@ -4,13 +4,13 @@ # # Original Creation Date: 2023-Oct-01 by @ExtremeFiretop. # Official Co-Author: @Martinski W. - Date: 2023-Nov-01 -# Last Modified: 2026-Mar-17 +# Last Modified: 2026-Mar-18 ################################################################### set -u ## Set version for each Production Release ## readonly SCRIPT_VERSION=1.6.0 -readonly SCRIPT_VERSTAG="26031700" +readonly SCRIPT_VERSTAG="26031823" readonly SCRIPT_NAME="MerlinAU" ## Set to "master" for Production Releases ## SCRIPT_BRANCH="dev" @@ -409,7 +409,7 @@ readonly LockTypeRegEx="(cliMenuLock|cliOptsLock|cliFileLock)" _FindLockFileTypes_() { grep -woE "$LockTypeRegEx" "$LockFilePath" | tr '\n' ' ' | sed 's/[ ]*$//' ; } -_ReleaseLock_() +_ReleaseLock_() { local lockType if [ $# -eq 0 ] || [ -z "$1" ] @@ -421,7 +421,7 @@ _ReleaseLock_() then if [ -z "$lockType" ] then sed -i "/^$$|/d" "$LockFilePath" - else sed -i "/.*|${1}$/d" "$LockFilePath" + else sed -i "/^$$|${1}$/d" "$LockFilePath" fi [ -s "$LockFilePath" ] && return 0 fi @@ -476,8 +476,7 @@ _AcquireLock_() retCode=1 lockTypeFound="" waitTimeoutSecs=0 - savedVerbose="$isVerbose" - isVerbose=true + savedVerbose="$isVerbose" ; isVerbose=true while true do @@ -531,6 +530,78 @@ _AcquireLock_() return "$retCode" } +##-------------------------------------## +## Added by Martinski W. [2026-Mar-18] ## +##-------------------------------------## +fwupMutexFLock_FD=576 +fwupMutexFLock_FN="/tmp/var/${ScriptFNameTag}_FW_Update.FLock" +fwupMutexFLock_OK=false #DO NOT have FLock# + +_ReleaseMutexFLock_() +{ + if [ $# -gt 0 ] && \ + [ "$1" = "checkLockOK" ] && \ + [ "$fwupMutexFLock_OK" != "true" ] + then return 0 + fi + + printf '' > "$fwupMutexFLock_FN" + flock -u "$fwupMutexFLock_FD" 2>/dev/null + fwupMutexFLock_OK=false +} + +##-------------------------------------## +## Added by Martinski W. [2026-Mar-18] ## +##-------------------------------------## +#--------------------------------------------------------------# +# This is a mutually exclusive, non-blocking FLOCK mechanism +# to be used when MerlinAU is perforning a F/W Update so that +# AMTM can check and prevent running automatic script updates +# while the F/W Update is in progress. +#--------------------------------------------------------------# +_AcquireMutexFLock_() +{ + local retCode savedVerbose + local procInfo procName procIDno procIDof="" + + savedVerbose="$isVerbose" ; isVerbose=true + + if [ -s "$fwupMutexFLock_FN" ] + then + procInfo="$(head -n1 "$fwupMutexFLock_FN")" + procName="$(echo "$procInfo" | cut -d'|' -f1)" + procIDno="$(echo "$procInfo" | cut -d'|' -f2)" + if [ -n "$procName" ] && [ -n "$procIDno" ] + then procIDof="$(pidof "$procName")" + fi + if [ -z "$procIDof" ] || \ + ! echo "$procIDof" | grep -qow "$procIDno" + then + Say "Stale F/W Update Lock Found. Resetting lock file..." + _ReleaseMutexFLock_ + fi + fi + + [ ! -s "$fwupMutexFLock_FN" ] && \ + eval exec "$fwupMutexFLock_FD>$fwupMutexFLock_FN" + + if flock -x -n "$fwupMutexFLock_FD" 2>/dev/null + then + printf "$(basename "$0")|$$\n" > "$fwupMutexFLock_FN" + retCode=0 ; fwupMutexFLock_OK=true + else + procInfo="$(head -n1 "$fwupMutexFLock_FN")" + if [ -n "$procInfo" ] + then procInfo="$(echo "$procInfo" | sed 's/|/, PID=/')" + fi + Say "${REDct}**ERROR**${NOct}: Another process [$procInfo] has the F/W Update Lock file." + retCode=1 ; fwupMutexFLock_OK=false + fi + + isVerbose="$savedVerbose" + return "$retCode" +} + ##-------------------------------------## ## Added by Martinski W. [2025-Sep-01] ## ##-------------------------------------## @@ -544,7 +615,9 @@ _DoExit_() { local exitCode=0 [ $# -gt 0 ] && [ -n "$1" ] && exitCode="$1" - _ReleaseLock_ ; exit "$exitCode" + _ReleaseLock_ + _ReleaseMutexFLock_ checkLockOK + exit "$exitCode" } ##-------------------------------------## @@ -9126,11 +9199,15 @@ _RunOfflineUpdateNow_() FW_DL_FPATH="${FW_ZIP_DIR}/${FW_FileName}.${extension}" _GnutonBuildSelection_ fi - if _AcquireLock_ cliFileLock + if _AcquireLock_ cliFileLock && \ + _AcquireMutexFLock_ then _RunFirmwareUpdateNow_ - _ReleaseLock_ cliFileLock + else + _WaitForEnterKey_ fi + _ReleaseLock_ cliFileLock + _ReleaseMutexFLock_ checkLockOK _ClearOfflineUpdateState_ else _ClearOfflineUpdateState_ 1 @@ -9953,10 +10030,12 @@ _PostRebootRunNow_() Say "END of $logMsg [$curWaitDelaySecs sec.]" sleep 30 ## Let's wait a bit & proceed ## - if _AcquireLock_ cliFileLock + if _AcquireLock_ cliFileLock && \ + _AcquireMutexFLock_ then _RunFirmwareUpdateNow_ _ReleaseLock_ cliFileLock + _ReleaseMutexFLock_ fi } @@ -11615,12 +11694,16 @@ _MainMenu_() HIDE_ROUTER_SECTION=true fi ;; - 1) if _AcquireLock_ cliFileLock + 1) if _AcquireLock_ cliFileLock && \ + _AcquireMutexFLock_ then _RunFirmwareUpdateNow_ - _ReleaseLock_ cliFileLock FlashStarted=false + else + _WaitForEnterKey_ fi + _ReleaseLock_ cliFileLock + _ReleaseMutexFLock_ checkLockOK ;; 2) _GetLoginCredentials_ ;; @@ -11822,10 +11905,12 @@ then case "$1" in run_now) - if _AcquireLock_ cliFileLock + if _AcquireLock_ cliFileLock && \ + _AcquireMutexFLock_ then _RunFirmwareUpdateNow_ _ReleaseLock_ cliFileLock + _ReleaseMutexFLock_ fi ;; processNodes) _ProcessMeshNodes_ false @@ -11914,7 +11999,8 @@ then ;; "${SCRIPT_NAME}checkfwupdate" | \ "${SCRIPT_NAME}checkfwupdate_bypassDays") - if _AcquireLock_ cliFileLock + if _AcquireLock_ cliFileLock && \ + _AcquireMutexFLock_ then if [ "$3" = "${SCRIPT_NAME}checkfwupdate_bypassDays" ] then bypassPostponedDays=true @@ -11923,6 +12009,7 @@ then webguiMode=true _RunFirmwareUpdateNow_ _ReleaseLock_ cliFileLock + _ReleaseMutexFLock_ fi ;; "${SCRIPT_NAME}scrptupdate" | \ diff --git a/README.md b/README.md index c1eb7be..6aa619f 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ # MerlinAU - AsusWRT-Merlin Firmware Auto Updater ## v1.6.0 -## 2026-Mar-17 +## 2026-Mar-19 ## WebUI: ![image](https://github.com/user-attachments/assets/9c1dff99-9c13-491b-a7fa-aff924d5f02e)