From e9673cad8810052ecbb6d5e04842d9aae78404e7 Mon Sep 17 00:00:00 2001 From: weichen Date: Mon, 12 Oct 2026 14:56:00 +0000 Subject: [PATCH] Wait for port release after stopping a service Why: on slow runners the orphaned http child of a stopped stub lingers a few hundred milliseconds past the parent's exit (ppid-watch suicide), and the immediately following start - notably the U2 rollback restart - classified the unparented listener as a foreign occupant and refused to start (CI run 3774). Evidence: test_svc_u2/identity/svc suites 82 OK locally with the wait in both stop paths. Impact: adds <=3s bounded wait in do_stop/do_stop_quiet after SIGTERM cleanup; no behavior change when the port is already free. --- scripts/svc.sh | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/scripts/svc.sh b/scripts/svc.sh index 34c2a4dd..af9ff500 100755 --- a/scripts/svc.sh +++ b/scripts/svc.sh @@ -3999,6 +3999,7 @@ do_stop() { proc_stop "$pid" rm -f "$ENV_PID" svc_clear_autostart + svc_wait_port_released c_ok "[$ENV_NAME] 已停止" hist_event stop ok "$pid" "SIGTERM" ;; @@ -4006,6 +4007,20 @@ do_stop() { return 0 } + +# svc_wait_port_released:停机后等子进程释放端口(最多 3s)。桩/组合产物的 http +# 子进程经 ppid-watch 自杀(≤0.5s 语义),慢机上略晚;不等会让紧跟的 start 把 +# 已无父的孤儿占口判成「非本服务」拒启(U2 回退实测,CI 慢机 run 3774)。 +svc_wait_port_released() { + local port="${ENV_ADDR##*:}" i=0 + [ -n "$port" ] || return 0 + while [ "$i" -lt 30 ] && port_listening "$port"; do + sleep 0.1 + i=$((i + 1)) + done + return 0 +} + # do_stop_quiet:deploy 前置——未运行时静默返回(同时清除期望态: # deploy 尾端的 start 成功会重新置位;失败则保持停止等人工介入)。 do_stop_quiet() { @@ -4028,6 +4043,7 @@ do_stop_quiet() { proc_stop "$pid" rm -f "$ENV_PID" svc_clear_autostart + svc_wait_port_released c_ok "[$ENV_NAME] 已停止" hist_event stop ok "$pid" "SIGTERM" ;;