From 73a96dcc3aaa048fb05c184ea8ff4a2a3505a3d6 Mon Sep 17 00:00:00 2001 From: Zihan Dai <99155080+PDGGK@users.noreply.github.com> Date: Mon, 31 Aug 2026 14:38:53 +1000 Subject: [PATCH 1/4] Fix stop-edge.sh failing to stop its own process when IOTDB_HOME is set start-edge.sh honours an IOTDB_HOME from the environment and passes that value to the JVM as -DIOTDB_HOME=..., while stop-edge.sh recomputed IOTDB_HOME from its own location and matched the command line against that string. When the two differ -- for example a versioned install reached through a symlink -- the stop declined to act on its own process, exited 0 and removed the PID file, so a service manager saw a successful stop while the process kept running. stop-edge.sh now honours IOTDB_HOME the same way start-edge.sh does, and falls back to comparing resolved paths when the literal match does not hit. The original literal comparison is tried first, so any command line that matched before still matches. --- scripts/sbin/stop-edge.sh | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/scripts/sbin/stop-edge.sh b/scripts/sbin/stop-edge.sh index 8f8f98ac64b1..eacbfa964a2d 100644 --- a/scripts/sbin/stop-edge.sh +++ b/scripts/sbin/stop-edge.sh @@ -20,7 +20,17 @@ # Stop IoTDB Edge (the merged ConfigNode + DataNode process). -IOTDB_HOME="$(cd "$(dirname "$0")"/.. && pwd)" +if [ -z "${IOTDB_HOME}" ]; then + IOTDB_HOME="$(cd "$(dirname "$0")"/.. && pwd)" +fi + +# Resolve symlinks and relative segments so that the same installation reached +# through a different path still compares equal. +resolve_home() { + (cd "$1" 2>/dev/null && pwd -P) || printf '%s' "$1" +} + +IOTDB_HOME_RESOLVED="$(resolve_home "${IOTDB_HOME}")" PID_FILE="${IOTDB_HOME}/edge.pid" @@ -31,9 +41,14 @@ is_same_edge_home() { return 0 ;; *) - return 1 ;; esac + # Fall back to comparing resolved paths, so that a start-edge.sh invoked with + # IOTDB_HOME pointing at a symlink is still recognised here. + local home="${command_line#*-DIOTDB_HOME=}" + home="${home%% -D*}" + [ -n "$home" ] && [ "$home" != "$command_line" ] || return 1 + [ "$(resolve_home "$home")" = "${IOTDB_HOME_RESOLVED}" ] } is_edge_process() { From 739dae25301adbb4c9ca6dad624ac0084eb81036 Mon Sep 17 00:00:00 2001 From: Zihan Dai <99155080+PDGGK@users.noreply.github.com> Date: Mon, 31 Aug 2026 20:29:44 +1000 Subject: [PATCH 2/4] Address review: resolve physically and only match absolute process homes Two problems in the previous version, both of which could stop a process belonging to a different installation. The helper used a plain cd before pwd -P. Because cd collapses ".." logically, a process home such as /../edge resolved against the symlink's parent rather than its target, so stopping one installation could terminate another. It now uses cd -P. The fallback also resolved relative process homes, such as the "." that start-edge.sh accepts and passes through unchanged, against the working directory of the stopping shell rather than that of the started process. A process started with IOTDB_HOME=. in one directory could therefore be matched and stopped from an unrelated installation. The fallback now only considers absolute values and leaves relative ones to the literal comparison, which matches the previous behaviour for them. --- scripts/sbin/stop-edge.sh | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/scripts/sbin/stop-edge.sh b/scripts/sbin/stop-edge.sh index eacbfa964a2d..b90a39875608 100644 --- a/scripts/sbin/stop-edge.sh +++ b/scripts/sbin/stop-edge.sh @@ -24,10 +24,12 @@ if [ -z "${IOTDB_HOME}" ]; then IOTDB_HOME="$(cd "$(dirname "$0")"/.. && pwd)" fi -# Resolve symlinks and relative segments so that the same installation reached -# through a different path still compares equal. +# Resolve to a physical absolute path so that the same installation reached +# through a different path still compares equal. "cd -P" is required: a plain +# "cd" collapses ".." logically, which would resolve "/../x" against the +# symlink's parent instead of its target. resolve_home() { - (cd "$1" 2>/dev/null && pwd -P) || printf '%s' "$1" + (cd -P -- "$1" 2>/dev/null && pwd -P) || printf '%s' "$1" } IOTDB_HOME_RESOLVED="$(resolve_home "${IOTDB_HOME}")" @@ -44,10 +46,21 @@ is_same_edge_home() { ;; esac # Fall back to comparing resolved paths, so that a start-edge.sh invoked with - # IOTDB_HOME pointing at a symlink is still recognised here. + # IOTDB_HOME pointing at a symlink is still recognised here. The value is + # delimited by the next " -D", which start-edge.sh always emits after + # -DIOTDB_HOME. If a hand-built command line ends with -DIOTDB_HOME, the + # extraction keeps the trailing arguments, the resolution below fails and the + # process is simply not matched -- never matched to the wrong installation. local home="${command_line#*-DIOTDB_HOME=}" home="${home%% -D*}" [ -n "$home" ] && [ "$home" != "$command_line" ] || return 1 + # Only absolute values can be resolved from here. A relative one such as "." + # is meaningful in the started process's working directory, not in ours, so + # resolving it here could match an unrelated installation. + case "$home" in + /*) ;; + *) return 1 ;; + esac [ "$(resolve_home "$home")" = "${IOTDB_HOME_RESOLVED}" ] } From cd4d7ef59166629ba142344ded70d0ea87621056 Mon Sep 17 00:00:00 2001 From: Zihan Dai <99155080+PDGGK@users.noreply.github.com> Date: Mon, 31 Aug 2026 20:39:25 +1000 Subject: [PATCH 3/4] Normalise IOTDB_HOME to a physical absolute path in start-edge.sh Taking the first of the two options suggested in review. The value start-edge.sh hands to the JVM as -DIOTDB_HOME is what stop-edge.sh matches on, so it should identify the installation on its own rather than depend on the path used to launch. Normalising it at that point removes the relative and symlinked forms at the source instead of resolving them later. The absolute-path guard in stop-edge.sh is kept as well, so a process started by an earlier start-edge.sh, whose command line may still carry a relative value, is left alone rather than matched against the stopping shell's directory. --- scripts/sbin/start-edge.sh | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/scripts/sbin/start-edge.sh b/scripts/sbin/start-edge.sh index be1a70ea6f79..48fca53befda 100644 --- a/scripts/sbin/start-edge.sh +++ b/scripts/sbin/start-edge.sh @@ -21,8 +21,16 @@ # Start IoTDB Edge: ConfigNode + DataNode in one JVM process. if [ -z "${IOTDB_HOME}" ]; then - export IOTDB_HOME="$(cd "$(dirname "$0")"/.. && pwd)" + IOTDB_HOME="$(dirname "$0")/.." fi +# Normalise to a physical absolute path. This value is handed to the JVM as +# -DIOTDB_HOME and is what stop-edge.sh matches on, so it has to identify the +# installation on its own, independently of the path used to launch. +IOTDB_HOME_PHYSICAL="$(cd -P -- "${IOTDB_HOME}" 2>/dev/null && pwd -P)" +if [ -n "${IOTDB_HOME_PHYSICAL}" ]; then + IOTDB_HOME="${IOTDB_HOME_PHYSICAL}" +fi +export IOTDB_HOME if [ -z "${IOTDB_CONF}" ]; then export IOTDB_CONF=${IOTDB_HOME}/conf fi From 25dbf74b57905ff4890800265381baec15b1d4d8 Mon Sep 17 00:00:00 2001 From: Zihan Dai <99155080+PDGGK@users.noreply.github.com> Date: Mon, 31 Aug 2026 21:00:41 +1000 Subject: [PATCH 4/4] Note why the fallback rejects an empty process home cd succeeds on an empty argument and returns the caller's working directory, so dropping the emptiness check would reopen the same class of mismatch as a relative value. Comment only. --- scripts/sbin/stop-edge.sh | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/scripts/sbin/stop-edge.sh b/scripts/sbin/stop-edge.sh index b90a39875608..0d1cb0bef9ef 100644 --- a/scripts/sbin/stop-edge.sh +++ b/scripts/sbin/stop-edge.sh @@ -56,7 +56,9 @@ is_same_edge_home() { [ -n "$home" ] && [ "$home" != "$command_line" ] || return 1 # Only absolute values can be resolved from here. A relative one such as "." # is meaningful in the started process's working directory, not in ours, so - # resolving it here could match an unrelated installation. + # resolving it here could match an unrelated installation. The emptiness check + # above matters for the same reason: "cd" succeeds on an empty argument and + # yields our own working directory. case "$home" in /*) ;; *) return 1 ;;