From 58a51c2ce94caa71830250793cc5b7a6efd82411 Mon Sep 17 00:00:00 2001 From: Nick Craig-Wood Date: Thu, 16 Apr 2026 17:29:06 +0100 Subject: [PATCH] fstest/testserver: add force-stop and reconcile stale refcounts run.bash holds a persistent refcount file in the shared state directory so multiple concurrent tests can share a single container. If a prior test_all run is killed (e.g. Ctrl-C), the count never reaches zero on the next run and the container is never stopped - forcing manual cleanup. Three fixes, all in fstest/testserver/init.d/run.bash: - On start, if the refcount is non-zero but no container is running, treat it as zero. Stops leaking through future runs. - reset now rm -rfs RUN_ROOT (the per-server state) instead of RUN_BASE (the shared parent) which was clobbering sibling services. - New force-stop verb unconditionally stops the container and zeroes the refcount. This is the primitive that the Go-side cleanup sweep will call at end-of-run. --- fstest/testserver/init.d/run.bash | 38 ++++++++++++++++++++++--------- 1 file changed, 27 insertions(+), 11 deletions(-) diff --git a/fstest/testserver/init.d/run.bash b/fstest/testserver/init.d/run.bash index ff1f70e94..4d59569c7 100644 --- a/fstest/testserver/init.d/run.bash +++ b/fstest/testserver/init.d/run.bash @@ -35,6 +35,15 @@ case "${1:-}" in rc=$(cat "${RUN_REF_COUNT}" 2>/dev/null || echo 0) + # If a previous run died without decrementing the refcount, the + # container will be gone but the count will still be > 0. Treat + # that as rc=0 so future stops actually reach zero and stop the + # server. + if (( rc > 0 )) && ! _is_running; then + echo "stale refcount ${rc} with no running container — resetting to 0" >&2 + rc=0 + fi + if (( rc == 0 )); then # First client: ensure a clean instance, then start and cache env if _is_running; then @@ -45,15 +54,6 @@ case "${1:-}" in exit 1 fi printf "%s\n" "$out" > "${RUN_OUTPUT}" - else - # Already owned: make sure it’s 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" > "${RUN_OUTPUT}" - fi fi rc=$((rc+1)); echo "${rc}" > "${RUN_REF_COUNT}" @@ -83,7 +83,23 @@ case "${1:-}" in trap '_release_lock' EXIT stop || true - rm -rf "${RUN_BASE}" + rm -rf "${RUN_ROOT}" + + trap - EXIT + _release_lock + ;; + + force-stop) + # Unconditionally stop the server and zero the refcount. Used as a + # safety-net sweep at the end of a test_all run so a stuck refcount + # can't leave a container running. + _acquire_lock + trap '_release_lock' EXIT + + if _is_running; then + stop || true + fi + echo 0 > "${RUN_REF_COUNT}" trap - EXIT _release_lock @@ -95,7 +111,7 @@ case "${1:-}" in ;; *) - echo "usage: $0 {start|stop|reset|status}" >&2 + echo "usage: $0 {start|stop|reset|force-stop|status}" >&2 exit 2 ;; esac