Skip to content

Commit ae0c6c7

Browse files
lroolleclaude
andcommitted
fix(tmux): pidfile hygiene, restore shim option surface
- bridge/host-daemon pidfiles: trust only a numeric PID whose command looks like our transport child (ssh/socat) — a stale pidfile with a reused PID no longer reports up or gets killed on stop; stale files are cleaned with a message - shim: restore -V/--version, -- end-of-options, and ignore non-option args like the old script (only unknown -flags error) Verified: stale-pidfile stop cleans without killing, bridge lifecycle still green, shellcheck clean. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
1 parent 2d01916 commit ae0c6c7

3 files changed

Lines changed: 50 additions & 10 deletions

File tree

deva.sh

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1359,35 +1359,52 @@ tmux_host_setup() {
13591359
# The socat fallback daemon exposes the host tmux socket over TCP with NO
13601360
# authentication — any process that can reach the port drives your tmux.
13611361
# Prefer the ssh transport; this exists for hosts without Remote Login.
1362+
# Stale pidfiles + PID reuse would make us report an unrelated process as
1363+
# our daemon (or kill it on stop); only trust a numeric PID whose command
1364+
# looks like the socat daemon.
1365+
tmux_host_daemon_pid() {
1366+
local pid_file="$1" pid
1367+
pid="$(cat "$pid_file" 2>/dev/null)" || return 1
1368+
case "$pid" in '' | *[!0-9]*) return 1 ;; esac
1369+
kill -0 "$pid" 2>/dev/null || return 1
1370+
ps -o command= -p "$pid" 2>/dev/null | grep -qE 'socat|deva-bridge-tmux-host' || return 1
1371+
echo "$pid"
1372+
}
1373+
13621374
tmux_host_daemon() {
13631375
local action="${1:-status}"
13641376
local state_dir="${XDG_STATE_HOME:-$HOME/.local/state}/deva/tmux"
13651377
local pid_file="$state_dir/host-daemon.pid"
13661378
local daemon="$SCRIPT_DIR/scripts/deva-bridge-tmux-host"
13671379
local bind="${DEVA_BRIDGE_BIND:-127.0.0.1}"
13681380
local port="${DEVA_BRIDGE_PORT:-41555}"
1381+
local pid
13691382
13701383
case "$action" in
13711384
status)
1372-
if [ -f "$pid_file" ] && kill -0 "$(cat "$pid_file")" 2>/dev/null; then
1373-
echo "host-daemon up (pid $(cat "$pid_file"), ${bind}:${port}) — UNAUTHENTICATED, prefer ssh"
1385+
if pid=$(tmux_host_daemon_pid "$pid_file"); then
1386+
echo "host-daemon up (pid $pid, ${bind}:${port}) — UNAUTHENTICATED, prefer ssh"
13741387
else
13751388
echo "host-daemon down"
13761389
return 1
13771390
fi
13781391
;;
13791392
stop)
13801393
if [ -f "$pid_file" ]; then
1381-
kill "$(cat "$pid_file")" 2>/dev/null || true
1394+
if pid=$(tmux_host_daemon_pid "$pid_file"); then
1395+
kill "$pid" 2>/dev/null || true
1396+
echo "host-daemon stopped"
1397+
else
1398+
echo "host-daemon pidfile was stale; cleaned up"
1399+
fi
13821400
rm -f "$pid_file"
1383-
echo "host-daemon stopped"
13841401
else
13851402
echo "host-daemon not running"
13861403
fi
13871404
;;
13881405
start)
1389-
if [ -f "$pid_file" ] && kill -0 "$(cat "$pid_file")" 2>/dev/null; then
1390-
echo "host-daemon already up (pid $(cat "$pid_file"))"
1406+
if pid=$(tmux_host_daemon_pid "$pid_file"); then
1407+
echo "host-daemon already up (pid $pid)"
13911408
return 0
13921409
fi
13931410
command -v socat >/dev/null 2>&1 || {

scripts/deva-bridge-tmux

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,14 @@ EOF
2121
}
2222

2323
QUIET=0
24+
VERSION="1.0.0"
2425

26+
# Same option surface as the old script: -V/--version, -- ends options,
27+
# non-option args are ignored (break), only unknown -flags error.
2528
while [ $# -gt 0 ]; do
2629
case $1 in
2730
-h | --help) usage; exit 0 ;;
31+
-V | --version) printf '%s %s (deva-tmux shim)\n' "$prog" "$VERSION"; exit 0 ;;
2832
-q | --quiet) QUIET=1 ;;
2933
-H | --host)
3034
[ $# -ge 2 ] || { echo "$prog: missing value for $1" >&2; exit 1; }
@@ -35,7 +39,9 @@ while [ $# -gt 0 ]; do
3539
-s | --socket)
3640
[ $# -ge 2 ] || { echo "$prog: missing value for $1" >&2; exit 1; }
3741
DEVA_TMUX_SOCK="$2"; export DEVA_TMUX_SOCK; shift ;;
38-
*) echo "$prog: unknown option: $1" >&2; exit 1 ;;
42+
--) shift; break ;;
43+
-*) echo "$prog: unknown option: $1" >&2; exit 1 ;;
44+
*) break ;;
3945
esac
4046
shift
4147
done

scripts/deva-tmux

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -150,8 +150,20 @@ EOF
150150
exit 1
151151
}
152152

153+
# A pidfile can go stale and the PID be reused by an unrelated process;
154+
# only treat it as ours if it is numeric AND the command looks like our
155+
# transport child (ssh or socat).
156+
bridge_pid_ours() {
157+
local pid
158+
pid=$(cat "$BRIDGE_PID" 2>/dev/null) || return 1
159+
[[ "$pid" =~ ^[0-9]+$ ]] || return 1
160+
kill -0 "$pid" 2>/dev/null || return 1
161+
ps -o command= -p "$pid" 2>/dev/null | grep -qE '(^|/| )(ssh|socat) ' || return 1
162+
echo "$pid"
163+
}
164+
153165
bridge_alive() {
154-
[[ -S "$BRIDGE_SOCK" && -f "$BRIDGE_PID" ]] && kill -0 "$(cat "$BRIDGE_PID")" 2>/dev/null
166+
[[ -S "$BRIDGE_SOCK" && -f "$BRIDGE_PID" ]] && bridge_pid_ours >/dev/null
155167
}
156168

157169
usage() {
@@ -329,9 +341,14 @@ cmd_bridge() {
329341
;;
330342
stop)
331343
if [[ -f "$BRIDGE_PID" ]]; then
332-
kill "$(cat "$BRIDGE_PID")" 2>/dev/null || true
344+
local pid
345+
if pid=$(bridge_pid_ours); then
346+
kill "$pid" 2>/dev/null || true
347+
echo "bridge stopped"
348+
else
349+
echo "bridge pidfile was stale; cleaned up"
350+
fi
333351
rm -f "$BRIDGE_PID" "$BRIDGE_SOCK"
334-
echo "bridge stopped"
335352
else
336353
echo "bridge not running"
337354
fi

0 commit comments

Comments
 (0)