diff --git a/ci/verify-backend.sh b/ci/verify-backend.sh index 1fb08c5..eedef97 100644 --- a/ci/verify-backend.sh +++ b/ci/verify-backend.sh @@ -33,7 +33,16 @@ chmod 700 "$NUGET_SCRATCH" export DOTNET_CLI_TELEMETRY_OPTOUT=1 DOTNET_NOLOGO=1 DOTNET_SKIP_FIRST_TIME_EXPERIENCE=1 DOTNET_GENERATE_ASPNET_CERTIFICATE=false exec 9> "$cache/.lock" -flock -w 900 9 || { echo "could not get the backend test cache lock" >&2; exit 1; } +# 拿不到锁时说一声是谁握着(不然步骤会静默等上 15 分钟) +if ! flock -n 9; then + echo "waiting for the backend test cache lock ($cache/.lock); held by:" >&2 + for fd in /proc/[0-9]*/fd/*; do + [[ "$(readlink "$fd" 2>/dev/null)" == "$cache/.lock" ]] || continue + pid="${fd#/proc/}"; pid="${pid%%/*}" + echo " pid $pid: $(tr '\0' ' ' < "/proc/$pid/cmdline" 2>/dev/null | cut -c1-150)" >&2 + done + flock -w 900 9 || { echo "could not get the backend test cache lock" >&2; exit 1; } +fi sync_sources() { mkdir -p "$src" @@ -61,7 +70,8 @@ sync_sources() { echo "synced sources: $changed changed, $stale removed" } -build() { (cd "$src/backend" && dotnet build MoShiro.slnx -c Release --nologo -v:q); } +# 9>&-:编译服务进程(VBCSCompiler、MSBuild 节点)会比步骤活得久,不能让它们继承锁的文件描述符,否则下一条流水线要一直等到它们自己退出 +build() { (cd "$src/backend" && dotnet build MoShiro.slnx -c Release --nologo -v:q 9>&-); } sync_sources if ! build; then @@ -96,7 +106,7 @@ run_with_timeout() { # This avoids setsid(1) forking away from the PID tracked by the old shell # watchdog, which could leave testhosts alive (and holding the cache lock) # after Woodpecker canceled the step. - (cd "$src/backend" && python3 "$root/ci/run-with-timeout.py" "$seconds" "$@") + (cd "$src/backend" && python3 "$root/ci/run-with-timeout.py" "$seconds" "$@" 9>&-) } # Ignore exit 8 from other assemblies with no matching tests; both suites have a hard wall-clock cap.