102 lines
3.4 KiB
Bash
Executable File
102 lines
3.4 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
set -euo pipefail
|
|
cd "$(dirname "$0")/.."
|
|
|
|
binary="$PWD/bin/uce_fastcgi.linux.bin"
|
|
root=$(mktemp -d /tmp/uce-server-arguments.XXXXXX)
|
|
listener_pid=""
|
|
cleanup() {
|
|
[[ -n "$listener_pid" ]] && kill "$listener_pid" 2>/dev/null || true
|
|
rm -rf "$root"
|
|
}
|
|
trap cleanup EXIT
|
|
|
|
cfg="$root/settings.cfg"
|
|
socket_path="$root/sentinel.sock"
|
|
cp /etc/uce/settings.cfg "$cfg"
|
|
sed -E -i \
|
|
-e "s|^[[:space:]]*FCGI_SOCKET_PATH[[:space:]]*=.*|FCGI_SOCKET_PATH=|" \
|
|
-e "s|^[[:space:]]*FCGI_PORT[[:space:]]*=.*|FCGI_PORT=|" \
|
|
-e "s|^[[:space:]]*CLI_SOCKET_PATH[[:space:]]*=.*|CLI_SOCKET_PATH=$socket_path|" \
|
|
-e "s|^[[:space:]]*HTTP_PORT[[:space:]]*=.*|HTTP_PORT=|" \
|
|
-e "s|^[[:space:]]*PROACTIVE_COMPILE_ENABLED[[:space:]]*=.*|PROACTIVE_COMPILE_ENABLED=false|" \
|
|
-e "s|^[[:space:]]*WORKER_COUNT[[:space:]]*=.*|WORKER_COUNT=1|" \
|
|
-e "s|^[[:space:]]*BIN_DIRECTORY[[:space:]]*=.*|BIN_DIRECTORY=$root/bin|" \
|
|
-e "s|^[[:space:]]*TMP_UPLOAD_PATH[[:space:]]*=.*|TMP_UPLOAD_PATH=$root/upload|" \
|
|
-e "s|^[[:space:]]*SESSION_PATH[[:space:]]*=.*|SESSION_PATH=$root/session|" \
|
|
"$cfg"
|
|
|
|
python3 -c 'import socket,sys,time; s=socket.socket(socket.AF_UNIX); s.bind(sys.argv[1]); s.listen(); time.sleep(30)' "$socket_path" &
|
|
listener_pid=$!
|
|
for _ in $(seq 1 50); do
|
|
[[ -S "$socket_path" ]] && break
|
|
sleep 0.02
|
|
done
|
|
[[ -S "$socket_path" ]]
|
|
socket_inode=$(stat -c %i "$socket_path")
|
|
|
|
invoke() {
|
|
local output="$1"
|
|
shift
|
|
local timeout_seconds="${INVOKE_TIMEOUT_SECONDS:-2}"
|
|
timeout --signal=TERM --kill-after=1s "$timeout_seconds" unshare --mount --fork \
|
|
bash -c 'mount --bind "$1" /etc/uce/settings.cfg; exec "$2" "${@:3}"' \
|
|
_ "$cfg" "$binary" "$@" >"$output.stdout" 2>"$output.stderr"
|
|
}
|
|
|
|
for option in --help -h; do
|
|
invoke "$root/help" "$option"
|
|
grep -q '^Usage: uce_fastcgi' "$root/help.stdout"
|
|
grep -q -- '--precompile' "$root/help.stdout"
|
|
grep -q -- '--serialize-module' "$root/help.stdout"
|
|
[[ ! -s "$root/help.stderr" ]]
|
|
done
|
|
|
|
for arguments in '--unknown' '--precompile extra' '--serialize-module' '--help extra'; do
|
|
read -r -a argv <<<"$arguments"
|
|
set +e
|
|
invoke "$root/invalid" "${argv[@]}"
|
|
rc=$?
|
|
set -e
|
|
[[ $rc -eq 2 ]]
|
|
grep -q '^invalid arguments$' "$root/invalid.stderr"
|
|
grep -q '^Usage: uce_fastcgi' "$root/invalid.stderr"
|
|
[[ ! -s "$root/invalid.stdout" ]]
|
|
done
|
|
|
|
cp bin/wasm/core.wasm "$root/serialize.wasm"
|
|
INVOKE_TIMEOUT_SECONDS=30 invoke "$root/serialize" --serialize-module "$root/serialize.wasm"
|
|
[[ -s "$root/serialize.cwasm" ]]
|
|
[[ ! -s "$root/serialize.stderr" ]]
|
|
|
|
# Serialization shares the unit compile lock. If the wasm path is replaced
|
|
# while the serializer is waiting, it must read the replacement and must not
|
|
# publish a stale native artifact for the old inode.
|
|
cp bin/wasm/core.wasm "$root/race.wasm"
|
|
exec 8>"$root/race.wasm.lock"
|
|
flock 8
|
|
INVOKE_TIMEOUT_SECONDS=30 invoke "$root/race" --serialize-module "$root/race.wasm" &
|
|
race_pid=$!
|
|
sleep 0.1
|
|
kill -0 "$race_pid"
|
|
printf 'not wasm\n' >"$root/race.wasm.next"
|
|
mv "$root/race.wasm.next" "$root/race.wasm"
|
|
flock -u 8
|
|
set +e
|
|
wait "$race_pid"
|
|
race_rc=$?
|
|
set -e
|
|
[[ $race_rc -eq 1 ]]
|
|
grep -Eqi 'wasm|magic|WebAssembly|compile' "$root/race.stderr"
|
|
[[ ! -e "$root/race.cwasm" ]]
|
|
if compgen -G "$root/race.cwasm.*.tmp" >/dev/null; then
|
|
echo "failed serialization left a temporary artifact" >&2
|
|
exit 1
|
|
fi
|
|
|
|
[[ -S "$socket_path" ]]
|
|
[[ "$(stat -c %i "$socket_path")" == "$socket_inode" ]]
|
|
kill -0 "$listener_pid"
|
|
|
|
echo 'server argument handling passed: help and invalid arguments exited before listener setup'
|