#!/usr/bin/env bash set -euo pipefail cd "$(dirname "$0")/.." if [[ "${1:-}" != "--inside" ]]; then exec timeout --signal=TERM --kill-after=5s 120s unshare --mount --fork --kill-child=TERM "$0" --inside fi root="/tmp/uce-cli-worker-isolation-$$" site="$root/site" work="$root/work" settings="$root/settings.cfg" log="$root/service.log" cli_socket="$root/run/cli.sock" fastcgi_socket="$root/run/fastcgi.sock" server_pid="" cleanup() { status=$? if [[ -n "$server_pid" ]] && kill -0 "$server_pid" 2>/dev/null; then kill -TERM "$server_pid" 2>/dev/null || true deadline=$((SECONDS + 10)) while kill -0 "$server_pid" 2>/dev/null && (( SECONDS < deadline )); do sleep 0.05; done if kill -0 "$server_pid" 2>/dev/null; then kill -KILL "$server_pid" 2>/dev/null || true; fi wait "$server_pid" 2>/dev/null || true fi if (( status != 0 )) && [[ -r "$log" ]]; then cat "$log" >&2; fi rm -rf "$root" return "$status" } trap cleanup EXIT mkdir -p "$site" "$work" "$root/run" "$root/session" "$root/upload" cp /etc/uce/settings.cfg "$settings" cat >>"$settings" <"$site/isolation.uce" <<'UCE' RENDER(Request& context) { print(request_perf()["worker_pid"].to_string()); } CLI(Request& context) { print(request_perf()["worker_pid"].to_string()); } UCE cat >"$site/nested.uce" <"$log" 2>&1 & server_pid=$! deadline=$((SECONDS + 20)) while [[ ! -S "$cli_socket" ]] && (( SECONDS < deadline )); do sleep 0.05; done [[ -S "$cli_socket" ]] || { echo "private UCE CLI socket was not ready" >&2; exit 1; } timeout --signal=TERM --kill-after=1s 30s scripts/uce-cli --socket "$cli_socket" /isolation.uce >/dev/null timeout --signal=TERM --kill-after=1s 30s scripts/uce-cli --socket "$cli_socket" /nested.uce | grep -Eq '^[0-9]+([.]0+)?$' fastcgi_request() { SCRIPT_FILENAME="$site/isolation.uce" SCRIPT_NAME=/isolation.uce REQUEST_URI=/isolation.uce REQUEST_METHOD=GET DOCUMENT_ROOT="$site" \ timeout --signal=TERM --kill-after=1s 10s cgi-fcgi -bind -connect "$fastcgi_socket" | tr -d '\r' | awk 'NF{last=$0} END{print last}' } fastcgi_request >/dev/null cli_request() { local output local deadline=$((SECONDS + 20)) while (( SECONDS < deadline )); do if output=$(timeout --signal=TERM --kill-after=1s 10s scripts/uce-cli --socket "$cli_socket" /isolation.uce 2>/dev/null); then printf '%s\n' "$output" return 0 fi sleep 0.05 done return 1 } cli_pids=() http_pids=() # Concurrent completions must count individually and retire both initial CLI # workers despite neither connection pool necessarily becoming idle first. concurrent_jobs=() for n in $(seq 1 12); do cli_request >"$root/concurrent-$n" & concurrent_jobs+=("$!") done for job in "${concurrent_jobs[@]}"; do wait "$job"; done mapfile -t concurrent_cli < <(cat "$root"/concurrent-* | sort -u) cli_pids+=("${concurrent_cli[@]}") for _ in $(seq 1 12); do cli_pids+=("$(cli_request)") http_pids+=("$(fastcgi_request)") done mapfile -t unique_cli < <(printf '%s\n' "${cli_pids[@]}" | sort -u) mapfile -t unique_http < <(printf '%s\n' "${http_pids[@]}" | sort -u) [[ ${#unique_cli[@]} -ge 4 ]] || { echo "CLI workers did not recycle after three requests: ${unique_cli[*]}" >&2; exit 1; } [[ ${#unique_http[@]} -ge 1 ]] || { echo "HTTP requests reached no public worker" >&2; exit 1; } for cli_pid in "${unique_cli[@]}"; do if printf '%s\n' "${unique_http[@]}" | grep -Fxq "$cli_pid"; then echo "CLI worker also served public HTTP: $cli_pid" >&2 exit 1 fi done [[ $(grep -c 'wasm FastCGI worker ready' "$log") -eq 2 ]] [[ $(grep -c 'wasm CLI worker ready' "$log") -ge 4 ]] echo "CLI worker isolation and recycling passed: CLI ${unique_cli[*]}, public ${unique_http[*]}" # A CLI-only runtime must not allocate a listener-less public Wasmtime worker. kill -TERM "$server_pid" wait "$server_pid" server_pid="" rm -f "$cli_socket" "$fastcgi_socket" cat >>"$settings" <"$log" bin/uce_fastcgi.linux.bin >"$log" 2>&1 & server_pid=$! deadline=$((SECONDS + 20)) while [[ ! -S "$cli_socket" ]] && (( SECONDS < deadline )); do sleep 0.05; done [[ -S "$cli_socket" ]] || { echo "CLI-only socket was not ready" >&2; exit 1; } cli_request >/dev/null [[ $(grep -c 'wasm CLI worker ready' "$log") -eq 1 ]] [[ $(grep -c 'wasm FastCGI worker ready' "$log") -eq 0 ]] echo "CLI-only worker allocation passed"