From 159e56a7f34b3ee13ded1b05954df8b172afe55d Mon Sep 17 00:00:00 2001 From: Vivek Lingaiah Date: Tue, 16 Dec 2025 22:47:23 +0000 Subject: [PATCH 01/10] Use flock command instead of lsof to check if run-command-handler is being used --- misc/run-command-shim | 53 +++++++++++++++++++------------------------ 1 file changed, 23 insertions(+), 30 deletions(-) diff --git a/misc/run-command-shim b/misc/run-command-shim index b6f1bbf..8dbe553 100644 --- a/misc/run-command-shim +++ b/misc/run-command-shim @@ -13,49 +13,41 @@ fi # in multiconfig case $ConfigExtensionName and $ConfigSequenceNumber should be set by the agent readonly EXTENSION_NAME=$ConfigExtensionName readonly SEQNO=$ConfigSequenceNumber +readonly LOCKFILE="./run-command-handler.lock" echo "ConfigExtensionName: $EXTENSION_NAME" echo "ConfigSequenceNumber: $SEQNO" echo Architecture: $ARCHITECTURE echo Binary: $HANDLER_BIN +LOCK_ACQUIRED=0 -check_binary_write_lock() { +get_lock() { set +e # disable exit on non-zero return code local retry_attempts=0 - while (( retry_attempts < 10 )); do - lsof_result="$(lsof -F ac ${bin})" - lsof_return_code=$? - if [ "$lsof_return_code" -eq 0 ]; then - #"lsof -F" outputs results in more parse-able format, "-F ac" option prints access mode and command name for process - #access mode and command names are prepended with a and c - file_mode="$(echo "$lsof_result" | awk 'match($0, /^a(.*)$/) {print $0}')" - process_name="$(echo "$lsof_result" | awk 'match($0, /^c(.*)$/) {print substr($0, RSTART+1, RLENGTH-1)}')" - found_write_lock=0 - file_mode_array=($file_mode) - i=0 - for name in $process_name - do - file_handle_mode=${file_mode_array[$i]} - echo "$name has access mode '$file_handle_mode' file handle on ${HANDLER_BIN}" - ## w and u are file descriptor modes for write and read/write access - if [[ $file_handle_mode == "aw" ]] || [[ $file_handle_mode == "au" ]]; then - found_write_lock=1 - fi - ((++i)) - done - if [ "$found_write_lock" -eq 0 ]; then - # did not find write lock on any file no need to wait or retry - break - fi + # Create lock file if it does not exist + if [ ! -f "$LOCKFILE" ]; then + touch "$LOCKFILE" + echo "Lock file '$LOCKFILE' has been created." + fi + + while (( retry_attempts < 10 )); do + # Acquire the exclusive (-x) and non-blocking (-n) lock on the lock file (side note: flock is part of util-linux package and is available by default on most Linux distros) + if ! flock -x -n $LOCKFILE; then + echo "Lock already held by another process. Retrying..." ((++retry_attempts)) - echo "waiting for process(es) with write handle on ${HANDLER_BIN}" echo "sleeping for 3 seconds before retry, attempt ${retry_attempts} of 10" sleep 3 + continue else + echo "Lock acquired on file '$LOCKFILE'" + LOCK_ACQUIRED=1 break fi done - # do not return error if file descriptor is open after retries expire, make a best effort attempt to start custom-script-extension + # Do not return error if lock not acquired even after retries expire, make a best effort attempt to start run-command-handler + if [ "$LOCK_ACQUIRED" -eq 0 ]; then + echo "Lock was not acquired on '$LOCKFILE' after retries. Making best-effort attempt to start run-command-handler..." + fi set -e return 0 } @@ -78,13 +70,14 @@ if [[ "$cmd" == "enable" ]]; then # for 'enable' command, double fork # to detach from the handler process tree to avoid getting terminated # after the 15-minute extension enabling timeout. - check_binary_write_lock + get_lock set -x # & will execute the binary on the backgraound and will not block current shell execution nohup "$bin" "$cmd" & else # execute the handler process as a child process - check_binary_write_lock + get_lock set -x "$bin" "$cmd" fi +# Exiting the script releases the lock on $LOCKFILE by closing the file descriptor associated with the lock. From 017cb08550d67445547efdf070b6fa160ea35dbd Mon Sep 17 00:00:00 2001 From: Vivek Lingaiah Date: Wed, 17 Dec 2025 20:07:21 +0000 Subject: [PATCH 02/10] Fix flock executing by using -c --- misc/run-command-shim | 86 +++++++++++++++++++++++-------------------- 1 file changed, 47 insertions(+), 39 deletions(-) diff --git a/misc/run-command-shim b/misc/run-command-shim index 8dbe553..6f411e2 100644 --- a/misc/run-command-shim +++ b/misc/run-command-shim @@ -20,38 +20,6 @@ echo Architecture: $ARCHITECTURE echo Binary: $HANDLER_BIN LOCK_ACQUIRED=0 -get_lock() { - set +e # disable exit on non-zero return code - local retry_attempts=0 - - # Create lock file if it does not exist - if [ ! -f "$LOCKFILE" ]; then - touch "$LOCKFILE" - echo "Lock file '$LOCKFILE' has been created." - fi - - while (( retry_attempts < 10 )); do - # Acquire the exclusive (-x) and non-blocking (-n) lock on the lock file (side note: flock is part of util-linux package and is available by default on most Linux distros) - if ! flock -x -n $LOCKFILE; then - echo "Lock already held by another process. Retrying..." - ((++retry_attempts)) - echo "sleeping for 3 seconds before retry, attempt ${retry_attempts} of 10" - sleep 3 - continue - else - echo "Lock acquired on file '$LOCKFILE'" - LOCK_ACQUIRED=1 - break - fi - done - # Do not return error if lock not acquired even after retries expire, make a best effort attempt to start run-command-handler - if [ "$LOCK_ACQUIRED" -eq 0 ]; then - echo "Lock was not acquired on '$LOCKFILE' after retries. Making best-effort attempt to start run-command-handler..." - fi - set -e - return 0 -} - if [ "$#" -ne 1 ]; then echo "Incorrect usage." echo "Usage: $0 " @@ -66,18 +34,58 @@ exec &> >(tee -ia "$LOG_DIR/$LOG_FILE") bin="$(readlink -f "$SCRIPT_DIR/$HANDLER_BIN")" cmd="$1" +# For commands other than 'enable', execute the handler process as a child process +commandToExecute = "$bin $cmd" + if [[ "$cmd" == "enable" ]]; then # for 'enable' command, double fork # to detach from the handler process tree to avoid getting terminated # after the 15-minute extension enabling timeout. - get_lock + # & will execute the binary on the background and will not block current shell execution + commandToExecute = "nohup $bin $cmd &" +fi + +### Retry logic to acquire lock and execute the command +set +e # disable exit on non-zero return code +local retry_attempts=0 + +# Create lock file if it does not exist +if [ ! -f "$LOCKFILE" ]; then + touch "$LOCKFILE" + echo "Lock file '$LOCKFILE' has been created." +fi + +while (( retry_attempts < 10 )); do set -x - # & will execute the binary on the backgraound and will not block current shell execution - nohup "$bin" "$cmd" & -else - # execute the handler process as a child process - get_lock + # Acquire the exclusive (-x) and non-blocking (-n) lock on the lock file and execute $commandToExecute(side note: flock is part of util-linux package and is available by default on most Linux distros) + flock -x -n "$LOCKFILE" -c "$commandToExecute" + flock_status=$? # Capture the exit status of the flock command + set +x + + if [ $flock_status -eq 1 ]; then + echo "Lock already held by another process. Retrying..." + ((++retry_attempts)) + echo "sleeping for 3 seconds before retry, attempt ${retry_attempts} of 10" + sleep 3 + continue + elif [ $flock_status -eq 0 ]; then + LOCK_ACQUIRED=1 + echo "Lock acquired on file '$LOCKFILE' and executed command '$commandToExecute' successfully. Exiting." + break + else + echo "Failed to execute command '$commandToExecute' with flock on file '$LOCKFILE'. Exiting with exit code $flock_status" + break + fi +done +### End of retry logic + +# Do not return error if lock not acquired even after retries expire, make a best effort attempt to start run-command-handler +if [ "$LOCK_ACQUIRED" -eq 0 ]; then + echo "Lock was not acquired on '$LOCKFILE' after retries. Making best-effort attempt to start run-command-handler..." set -x - "$bin" "$cmd" + $commandToExecute + set +x fi +set -e + # Exiting the script releases the lock on $LOCKFILE by closing the file descriptor associated with the lock. From d3b299c307e0476c93700ead235e15af5941adbd Mon Sep 17 00:00:00 2001 From: Vivek Lingaiah Date: Wed, 17 Dec 2025 20:43:52 +0000 Subject: [PATCH 03/10] Fix commandToExecure --- misc/run-command-shim | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/misc/run-command-shim b/misc/run-command-shim index 6f411e2..6457625 100644 --- a/misc/run-command-shim +++ b/misc/run-command-shim @@ -35,14 +35,14 @@ bin="$(readlink -f "$SCRIPT_DIR/$HANDLER_BIN")" cmd="$1" # For commands other than 'enable', execute the handler process as a child process -commandToExecute = "$bin $cmd" +commandToExecute = "${bin} ${cmd}" if [[ "$cmd" == "enable" ]]; then # for 'enable' command, double fork # to detach from the handler process tree to avoid getting terminated # after the 15-minute extension enabling timeout. # & will execute the binary on the background and will not block current shell execution - commandToExecute = "nohup $bin $cmd &" + commandToExecute = "nohup ${bin} ${cmd} &" fi ### Retry logic to acquire lock and execute the command @@ -52,7 +52,7 @@ local retry_attempts=0 # Create lock file if it does not exist if [ ! -f "$LOCKFILE" ]; then touch "$LOCKFILE" - echo "Lock file '$LOCKFILE' has been created." + echo "Lock file $LOCKFILE has been created." fi while (( retry_attempts < 10 )); do @@ -70,10 +70,10 @@ while (( retry_attempts < 10 )); do continue elif [ $flock_status -eq 0 ]; then LOCK_ACQUIRED=1 - echo "Lock acquired on file '$LOCKFILE' and executed command '$commandToExecute' successfully. Exiting." + echo "Lock acquired on file $LOCKFILE and executed command $commandToExecute successfully. Exiting." break else - echo "Failed to execute command '$commandToExecute' with flock on file '$LOCKFILE'. Exiting with exit code $flock_status" + echo "Failed to execute command $commandToExecute with flock on file $LOCKFILE. Exiting with exit code $flock_status" break fi done @@ -81,7 +81,7 @@ done # Do not return error if lock not acquired even after retries expire, make a best effort attempt to start run-command-handler if [ "$LOCK_ACQUIRED" -eq 0 ]; then - echo "Lock was not acquired on '$LOCKFILE' after retries. Making best-effort attempt to start run-command-handler..." + echo "Lock was not acquired on $LOCKFILE after retries. Making best-effort attempt to start run-command-handler..." set -x $commandToExecute set +x From 772ba60eb831ff9ec74c705d61783b08b2ba6c55 Mon Sep 17 00:00:00 2001 From: Vivek Lingaiah Date: Wed, 17 Dec 2025 20:58:11 +0000 Subject: [PATCH 04/10] Fix commandToExecute assignment --- misc/run-command-shim | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/misc/run-command-shim b/misc/run-command-shim index 6457625..51359b8 100644 --- a/misc/run-command-shim +++ b/misc/run-command-shim @@ -35,14 +35,14 @@ bin="$(readlink -f "$SCRIPT_DIR/$HANDLER_BIN")" cmd="$1" # For commands other than 'enable', execute the handler process as a child process -commandToExecute = "${bin} ${cmd}" +commandToExecute="$bin $cmd" if [[ "$cmd" == "enable" ]]; then # for 'enable' command, double fork # to detach from the handler process tree to avoid getting terminated # after the 15-minute extension enabling timeout. # & will execute the binary on the background and will not block current shell execution - commandToExecute = "nohup ${bin} ${cmd} &" + commandToExecute="nohup $bin $cmd &" fi ### Retry logic to acquire lock and execute the command From 4b5e7f1ed408666fc082e284854944c36de9da02 Mon Sep 17 00:00:00 2001 From: Vivek Lingaiah Date: Wed, 17 Dec 2025 21:07:53 +0000 Subject: [PATCH 05/10] Fix logging into commandExecution logs --- misc/run-command-shim | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/misc/run-command-shim b/misc/run-command-shim index 51359b8..9344f51 100644 --- a/misc/run-command-shim +++ b/misc/run-command-shim @@ -47,7 +47,7 @@ fi ### Retry logic to acquire lock and execute the command set +e # disable exit on non-zero return code -local retry_attempts=0 +retry_attempts=0 # Create lock file if it does not exist if [ ! -f "$LOCKFILE" ]; then @@ -55,13 +55,12 @@ if [ ! -f "$LOCKFILE" ]; then echo "Lock file $LOCKFILE has been created." fi +set -x while (( retry_attempts < 10 )); do - set -x # Acquire the exclusive (-x) and non-blocking (-n) lock on the lock file and execute $commandToExecute(side note: flock is part of util-linux package and is available by default on most Linux distros) flock -x -n "$LOCKFILE" -c "$commandToExecute" flock_status=$? # Capture the exit status of the flock command - set +x - + if [ $flock_status -eq 1 ]; then echo "Lock already held by another process. Retrying..." ((++retry_attempts)) @@ -77,6 +76,7 @@ while (( retry_attempts < 10 )); do break fi done +set +x ### End of retry logic # Do not return error if lock not acquired even after retries expire, make a best effort attempt to start run-command-handler From 40895602f265aec5c3fb83d2c39dc940ebfb9b41 Mon Sep 17 00:00:00 2001 From: Vivek Lingaiah Date: Tue, 4 Aug 2026 03:24:16 +0000 Subject: [PATCH 06/10] Use fuser command instead of lsof to detect conflicts while running RC --- misc/run-command-shim | 67 +++++++++++++++++++------------------------ 1 file changed, 30 insertions(+), 37 deletions(-) mode change 100644 => 100755 misc/run-command-shim diff --git a/misc/run-command-shim b/misc/run-command-shim old mode 100644 new mode 100755 index 9344f51..87ceee0 --- a/misc/run-command-shim +++ b/misc/run-command-shim @@ -13,12 +13,11 @@ fi # in multiconfig case $ConfigExtensionName and $ConfigSequenceNumber should be set by the agent readonly EXTENSION_NAME=$ConfigExtensionName readonly SEQNO=$ConfigSequenceNumber -readonly LOCKFILE="./run-command-handler.lock" + echo "ConfigExtensionName: $EXTENSION_NAME" echo "ConfigSequenceNumber: $SEQNO" echo Architecture: $ARCHITECTURE echo Binary: $HANDLER_BIN -LOCK_ACQUIRED=0 if [ "$#" -ne 1 ]; then echo "Incorrect usage." @@ -45,47 +44,41 @@ if [[ "$cmd" == "enable" ]]; then commandToExecute="nohup $bin $cmd &" fi -### Retry logic to acquire lock and execute the command +### Retry logic to check if RunCommand binary is open for write and execute the command set +e # disable exit on non-zero return code retry_attempts=0 -# Create lock file if it does not exist -if [ ! -f "$LOCKFILE" ]; then - touch "$LOCKFILE" - echo "Lock file $LOCKFILE has been created." +set -x +if command -v fuser &>/dev/null; then + while (( retry_attempts < 10 )); do + # Use fuser to detect if the run command binary is open for write to help detect potential conflicts like 'text file busy' errors that prevents execution of Run Command binary. + fuser_output=$(fuser -vw "$bin" 2>&1) + fuser_status=$? + + # Use 10 retries with 3 seconds sleep between retries to allow for any potential conflicts to resolve before executing the Run Command binary. + if [ $fuser_status -eq 0 ]; then + echo "RunCommand binary $bin is open for write. User(s) with write access:" + echo "$fuser_output" + echo "Binary is open for write. Allowing execution via best-effort path after all retries have been exhausted..." + ((++retry_attempts)) + echo "sleeping for 3 seconds before retry, attempt ${retry_attempts} of 10" + sleep 3 + continue + else + echo "Binary $bin is not open for write. All good. Proceeding with execution..." + break + fi + done +else + echo "INFO: Not an error. fuser command not found. Install 'psmic' package to use fuser for checking if the Run Command binary is open for write to detect potential conflicts like 'text file busy' errors while executing Run Command binary. Proceeding with best-effort execution..." fi +set +x +### End of retry logic set -x -while (( retry_attempts < 10 )); do - # Acquire the exclusive (-x) and non-blocking (-n) lock on the lock file and execute $commandToExecute(side note: flock is part of util-linux package and is available by default on most Linux distros) - flock -x -n "$LOCKFILE" -c "$commandToExecute" - flock_status=$? # Capture the exit status of the flock command - - if [ $flock_status -eq 1 ]; then - echo "Lock already held by another process. Retrying..." - ((++retry_attempts)) - echo "sleeping for 3 seconds before retry, attempt ${retry_attempts} of 10" - sleep 3 - continue - elif [ $flock_status -eq 0 ]; then - LOCK_ACQUIRED=1 - echo "Lock acquired on file $LOCKFILE and executed command $commandToExecute successfully. Exiting." - break - else - echo "Failed to execute command $commandToExecute with flock on file $LOCKFILE. Exiting with exit code $flock_status" - break - fi -done +echo "Starting run-command-handler..." +$commandToExecute +echo "run-command-handler finished." set +x -### End of retry logic -# Do not return error if lock not acquired even after retries expire, make a best effort attempt to start run-command-handler -if [ "$LOCK_ACQUIRED" -eq 0 ]; then - echo "Lock was not acquired on $LOCKFILE after retries. Making best-effort attempt to start run-command-handler..." - set -x - $commandToExecute - set +x -fi set -e - -# Exiting the script releases the lock on $LOCKFILE by closing the file descriptor associated with the lock. From 43eea29f0ad69634e468a354039b45cd37bb3c62 Mon Sep 17 00:00:00 2001 From: Vivek Lingaiah Date: Fri, 7 Aug 2026 04:28:37 +0000 Subject: [PATCH 07/10] Address PR comments --- misc/run-command-shim | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/misc/run-command-shim b/misc/run-command-shim index 87ceee0..343798c 100755 --- a/misc/run-command-shim +++ b/misc/run-command-shim @@ -34,14 +34,14 @@ bin="$(readlink -f "$SCRIPT_DIR/$HANDLER_BIN")" cmd="$1" # For commands other than 'enable', execute the handler process as a child process -commandToExecute="$bin $cmd" +commandToExecute="'$bin' '$cmd'" if [[ "$cmd" == "enable" ]]; then # for 'enable' command, double fork # to detach from the handler process tree to avoid getting terminated # after the 15-minute extension enabling timeout. # & will execute the binary on the background and will not block current shell execution - commandToExecute="nohup $bin $cmd &" + commandToExecute="nohup '$bin' '$cmd' &" fi ### Retry logic to check if RunCommand binary is open for write and execute the command @@ -49,14 +49,14 @@ set +e # disable exit on non-zero return code retry_attempts=0 set -x -if command -v fuser &>/dev/null; then +if command -v fuser &>/dev/null; then # check if fuser command is available while (( retry_attempts < 10 )); do # Use fuser to detect if the run command binary is open for write to help detect potential conflicts like 'text file busy' errors that prevents execution of Run Command binary. fuser_output=$(fuser -vw "$bin" 2>&1) fuser_status=$? # Use 10 retries with 3 seconds sleep between retries to allow for any potential conflicts to resolve before executing the Run Command binary. - if [ $fuser_status -eq 0 ]; then + if [ $fuser_status -eq 0 ]; then # atleast one process was found which has opened the binary in write mode. echo "RunCommand binary $bin is open for write. User(s) with write access:" echo "$fuser_output" echo "Binary is open for write. Allowing execution via best-effort path after all retries have been exhausted..." @@ -64,18 +64,19 @@ if command -v fuser &>/dev/null; then echo "sleeping for 3 seconds before retry, attempt ${retry_attempts} of 10" sleep 3 continue - else + elif [ $fuser_status -eq 1 ]; then echo "Binary $bin is not open for write. All good. Proceeding with execution..." break + else + echo "Unexpected fuser error with error code $fuser_status while checking if $bin is open for write using fuser command. Proceeding with best-effort execution..." + break fi done else echo "INFO: Not an error. fuser command not found. Install 'psmic' package to use fuser for checking if the Run Command binary is open for write to detect potential conflicts like 'text file busy' errors while executing Run Command binary. Proceeding with best-effort execution..." fi -set +x ### End of retry logic -set -x echo "Starting run-command-handler..." $commandToExecute echo "run-command-handler finished." From 69d225aef00516a9b128199c58714f44698cc9d7 Mon Sep 17 00:00:00 2001 From: Vivek Lingaiah Date: Fri, 7 Aug 2026 06:12:01 +0000 Subject: [PATCH 08/10] Minor error redirection change --- misc/run-command-shim | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/misc/run-command-shim b/misc/run-command-shim index 343798c..1c5b381 100755 --- a/misc/run-command-shim +++ b/misc/run-command-shim @@ -27,7 +27,7 @@ fi # Redirect logs of the handler process mkdir -p "$LOG_DIR" -exec &> >(tee -ia "$LOG_DIR/$LOG_FILE") +exec &> >(tee -ia "$LOG_DIR/$LOG_FILE") 2>&1 # Start handling the process in the background bin="$(readlink -f "$SCRIPT_DIR/$HANDLER_BIN")" From f9b0debc438f1e0faa88cb8297631e7dc722c70f Mon Sep 17 00:00:00 2001 From: Vivek Lingaiah Date: Fri, 7 Aug 2026 06:35:37 +0000 Subject: [PATCH 09/10] revert small change --- misc/run-command-shim | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/misc/run-command-shim b/misc/run-command-shim index 1c5b381..343798c 100755 --- a/misc/run-command-shim +++ b/misc/run-command-shim @@ -27,7 +27,7 @@ fi # Redirect logs of the handler process mkdir -p "$LOG_DIR" -exec &> >(tee -ia "$LOG_DIR/$LOG_FILE") 2>&1 +exec &> >(tee -ia "$LOG_DIR/$LOG_FILE") # Start handling the process in the background bin="$(readlink -f "$SCRIPT_DIR/$HANDLER_BIN")" From ed804c6876a8a5fcfc745ee92cd52b6b8953fb16 Mon Sep 17 00:00:00 2001 From: Vivek Lingaiah Date: Wed, 19 Aug 2026 18:28:25 +0000 Subject: [PATCH 10/10] Address PR comment --- misc/run-command-shim | 1 + 1 file changed, 1 insertion(+) diff --git a/misc/run-command-shim b/misc/run-command-shim index 343798c..9784d4c 100755 --- a/misc/run-command-shim +++ b/misc/run-command-shim @@ -68,6 +68,7 @@ if command -v fuser &>/dev/null; then # check if fuser command is available echo "Binary $bin is not open for write. All good. Proceeding with execution..." break else + echo "$fuser_output" echo "Unexpected fuser error with error code $fuser_status while checking if $bin is open for write using fuser command. Proceeding with best-effort execution..." break fi