1
0
mirror of https://github.com/rclone/rclone.git synced 2026-01-04 17:43:50 +00:00

testserver: fix tests failing due to stopped servers

Before this fix there were various issues with the test server
framework, most noticeably servers stopping when they shouldn't
causing timeouts. This was caused by the reference counting in the Go
code not being engineered to work in multiple processes so it was not
working at all properly.

This fix moves the reference counting logic to the start scripts and
in turn removes that logic from the Go code. This means that the
reference counting is now global and works correctly over multiple
processes.
This commit is contained in:
Nick Craig-Wood
2025-11-04 11:08:45 +00:00
parent 700e6e11fd
commit 55655efabf
3 changed files with 173 additions and 109 deletions

View File

@@ -1,17 +1,101 @@
#!/usr/bin/env bash
set -euo pipefail
case "$1" in
start)
start
;;
stop)
stop
;;
status)
status
;;
*)
echo "usage: $0 start|stop|status" >&2
exit 1
;;
BASE="${STATE_DIR:-${XDG_RUNTIME_DIR:-/tmp}/rclone-test-server}"
NAME="$(basename "$0")"
ROOT="${BASE}/${NAME}"
STATE="${ROOT}/state"
LOCKF="${ROOT}/lock"
REFC="${STATE}/refcount"
ENVF="${STATE}/env"
mkdir -p "${STATE}"
[[ -f "${REFC}" ]] || echo 0 >"${REFC}"
[[ -f "${ENVF}" ]] || : >"${ENVF}"
: > "${LOCKF}" # ensure file exists
# status helper that won't trip set -e
_is_running() { set +e; status >/dev/null 2>&1; local rc=$?; set -e; return $rc; }
_acquire_lock() {
# open fd 9 on lock file and take exclusive lock
exec 9>"${LOCKF}"
flock -x 9
}
_release_lock() {
flock -u 9
exec 9>&-
}
case "${1:-}" in
start)
_acquire_lock
trap '_release_lock' EXIT
rc=$(cat "${REFC}" 2>/dev/null || echo 0)
if (( rc == 0 )); then
# First client: ensure a clean instance, then start and cache env
if _is_running; then
stop || true
fi
if ! out="$(start)"; then
echo "failed to start" >&2
exit 1
fi
printf "%s\n" "$out" > "${ENVF}"
else
# Already owned: make sure its still up; if not, restart and refresh env
if ! _is_running; then
if ! out="$(start)"; then
echo "failed to restart" >&2
exit 1
fi
printf "%s\n" "$out" > "${ENVF}"
fi
fi
rc=$((rc+1)); echo "${rc}" > "${REFC}"
cat "${ENVF}"
trap - EXIT
_release_lock
;;
stop)
_acquire_lock
trap '_release_lock' EXIT
rc=$(cat "${REFC}" 2>/dev/null || echo 0)
if (( rc > 0 )); then rc=$((rc-1)); fi
echo "${rc}" > "${REFC}"
if (( rc == 0 )) && _is_running; then
stop || true
fi
trap - EXIT
_release_lock
;;
reset)
_acquire_lock
trap '_release_lock' EXIT
stop || true
rm -rf "${BASE}"
trap - EXIT
_release_lock
;;
status)
# passthrough; do NOT take the lock
status
;;
*)
echo "usage: $0 {start|stop|reset|status}" >&2
exit 2
;;
esac