115 lines
6.2 KiB
Bash
Executable file
115 lines
6.2 KiB
Bash
Executable file
#!/bin/sh
|
|
# Stress test of compiler memory across settles (MEMSAFE.DESIGN.md; replaces zone_swap.sh/zone_stress.sh).
|
|
# Memory is freed only by its owner's Drop, never in bulk, so this checks the runtime side of that
|
|
# rule under the worst interleaving we can force: each package starts hidden and muted (cold cache
|
|
# of its own) with
|
|
# MAKEPAD_RUN_SETTLE_STRESS=$PERIOD a settle (settle_drop, retire, trim) every PERIOD ms while
|
|
# compiles, O3 bursts and speculation run,
|
|
# MAKEPAD_RUN_ZAP=1 every freed compiler / job-arena block filled with 0xcd,
|
|
# MAKEPAD_RUN_JOB_CHECK=1 a line for every job that left blocks in its job arena.
|
|
# Probes across the settles (the 2026-10-20 P0: inspect's records and a counted fn): `count $PROBE` is
|
|
# installed, removed and installed again three times before the first settle; after RUNS settles the
|
|
# counted fn must keep counting, and rm + count again must work. Then a clean quit (exit status 0).
|
|
# The output may hold no fault, panic, abort or POISONED line; job-arena survivors are reported (they
|
|
# cost memory, not safety) and fail the run only with STRICT_JOBS=1.
|
|
# Run from the workspace root after `cargo build --release -p makepad-run` and `-p makepad-remote`.
|
|
# PACKAGES (default "makepad-app-calculator"), PERIOD (ms, default 300), AFTER (seconds of stress after
|
|
# the first settle, default 8), WAIT (seconds to wait for the first frame / settle, default 90), TARGET
|
|
# (default target/release). A run passes only with at least one settle rebuild (NEED_REBUILD=0: off).
|
|
# Logs stay in a scratch directory under TMPDIR (removed on success unless KEEP=1).
|
|
T=${TARGET:-target/release}
|
|
PACKAGES=${PACKAGES:-makepad-app-calculator}
|
|
if [ ! -x "$T/makepad-remote" ]; then
|
|
echo "settle_stress: FAIL: $T/makepad-remote is missing (cargo build --release -p makepad-remote): the probes cannot be driven"
|
|
exit 2
|
|
fi
|
|
PERIOD=${PERIOD:-300}
|
|
AFTER=${AFTER:-8}
|
|
WAIT=${WAIT:-90}
|
|
PROBE=${PROBE:-makepad_platform::remote::imp::path_dump}
|
|
DRIVE=${DRIVE:-dump paths=1}
|
|
dir=$(mktemp -d "${TMPDIR:-/tmp}/settle_stress.XXXXXX") || exit 1
|
|
fails=0
|
|
k=0
|
|
for pkg in $PACKAGES; do
|
|
d=$dir/$pkg
|
|
k=$((k + 1)); td=$dir/t$k
|
|
mkdir -p "$d/home" "$td"
|
|
MAKEPAD_HIDE_WINDOWS=1 MAKEPAD_MUTE=1 SANDBOX_MUTE=1 MUSIC_MUTE=1 MAKEPAD_REMOTE=1 MAKEPAD_HOME="$d/home" TMPDIR="$td" \
|
|
MAKEPAD_RUN_HOME="$d/runhome" MAKEPAD_RUN_CACHE_DIR="$d/cache" MAKEPAD_WINDOW=1280x800@1 MAKEPAD_RUN_VERBOSE=1 \
|
|
MAKEPAD_RUN_SETTLE_STRESS="$PERIOD" MAKEPAD_RUN_ZAP=1 MAKEPAD_RUN_JOB_CHECK=1 \
|
|
"$T/makepad" run "$pkg" > "$d/run.log" 2>&1 &
|
|
pid=$!
|
|
: > "$d/fixture.log"
|
|
ask() { TMPDIR="$td" "$T/makepad" inspect $pid "$@" as=json >> "$d/probes.log" 2>&1; }
|
|
drive() { for r in 1 2 3; do TMPDIR="$td" "$T/makepad-remote" app $pid $DRIVE > /dev/null 2>&1; done; }
|
|
hits() { TMPDIR="$td" "$T/makepad" inspect $pid probes as=json 2>/dev/null | grep -o '"hits":[0-9]*' | head -1 | cut -d: -f2; }
|
|
settles() { grep -ac "makepad-run mem: settle at" "$d/run.log"; }
|
|
n=0
|
|
until TMPDIR="$td" "$T/makepad" inspect $pid ping > /dev/null 2>&1 && grep -q "first frame at" "$d/run.log"; do
|
|
n=$((n + 1)); [ $n -ge $((WAIT * 5)) ] && break
|
|
kill -0 $pid 2>/dev/null || break
|
|
sleep 0.2
|
|
done
|
|
drive
|
|
for r in 1 2 3; do ask count "$PROBE"; drive; ask rm all; done
|
|
ask count "$PROBE"
|
|
n=0
|
|
until [ "$(settles)" -gt 0 ]; do
|
|
n=$((n + 1)); [ $n -ge $((WAIT * 5)) ] && break
|
|
kill -0 $pid 2>/dev/null || break
|
|
sleep 0.2
|
|
done
|
|
s0=$(settles)
|
|
if [ "$s0" -gt 0 ]; then
|
|
h0=$(hits)
|
|
i=0
|
|
while [ $i -lt "$AFTER" ]; do drive; sleep 1; i=$((i + 1)); done
|
|
# and the first settle rebuild (it waits for the run's mid-run collected write)
|
|
n=0
|
|
until grep -aq "makepad-run settle rebuild at" "$d/run.log"; do
|
|
n=$((n + 1)); [ $n -ge $((WAIT * 5)) ] && break
|
|
kill -0 $pid 2>/dev/null || break
|
|
sleep 0.2
|
|
done
|
|
i=0
|
|
while [ $i -lt 3 ]; do drive; sleep 1; i=$((i + 1)); done
|
|
TMPDIR="$td" "$T/makepad" inspect $pid memory > "$d/memory.log" 2>&1
|
|
h1=$(hits)
|
|
ask rm all
|
|
ask count "$PROBE"
|
|
drive
|
|
h2=$(hits)
|
|
s1=$(settles)
|
|
echo "settle_stress: settles ${s0} -> ${s1}; probe hits ${h0:-none} -> ${h1:-none}; reinstalled: ${h2:-none}" >> "$d/fixture.log"
|
|
[ -n "$h0" ] && [ -n "$h1" ] && [ "$h1" -gt "$h0" ] || echo "settle_stress: $pkg: the counted fn stopped counting across the settles" >> "$d/fixture.log"
|
|
[ -n "$h2" ] && [ "$h2" -gt 0 ] || echo "settle_stress: $pkg: count after the settles failed" >> "$d/fixture.log"
|
|
[ "$s1" -gt "$s0" ] || echo "settle_stress: $pkg: no settle under stress after the first" >> "$d/fixture.log"
|
|
else
|
|
echo "settle_stress: $pkg: no settle within ${WAIT} s" >> "$d/fixture.log"
|
|
fi
|
|
alive=1
|
|
kill -0 $pid 2>/dev/null || alive=0
|
|
[ $alive = 1 ] && kill -TERM $pid
|
|
wait $pid
|
|
rc=$?
|
|
why=
|
|
[ $alive = 0 ] && why="$why died under the stress (status $rc);"
|
|
[ $alive = 1 ] && [ $rc -ne 0 ] && why="$why exit status $rc;"
|
|
fx=$(grep -aE "no settle|stopped counting|failed" "$d/fixture.log" | head -1)
|
|
[ -n "$fx" ] && why="$why $fx;"
|
|
bad=$(grep -aE "makepad-run: fault|fault (at|in) |panicked|Segmentation|Bus error|SIGSEGV|SIGBUS|SIGILL|Aborted|POISONED|run monitor ended|state may be corrupt" "$d/run.log" | head -2)
|
|
[ -n "$bad" ] && why="$why $bad;"
|
|
jobs=$(grep -ac "^makepad-run job:" "$d/run.log")
|
|
rebuilds=$(grep -ac "makepad-run settle rebuild at" "$d/run.log")
|
|
[ "${NEED_REBUILD:-1}" = 1 ] && [ "$rebuilds" -eq 0 ] && why="$why no settle rebuild ($(grep -a 'settle rebuild deferred\|settle rebuild refused' "$d/run.log" | tail -1 | cut -c1-160));"
|
|
[ "${STRICT_JOBS:-0}" = 1 ] && [ "$jobs" -gt 0 ] && why="$why $jobs jobs left survivors;"
|
|
if [ -z "$why" ]; then
|
|
echo "settle_stress: $pkg: ok ($(grep -a 'settles' "$d/fixture.log" | cut -c16-); $rebuilds settle rebuilds; $jobs jobs left survivors)"
|
|
else
|
|
echo "settle_stress: $pkg: FAIL:$why (logs $d/run.log, $d/fixture.log)"
|
|
fails=$((fails + 1))
|
|
fi
|
|
done
|
|
[ $fails -eq 0 ] && [ "${KEEP:-0}" != 1 ] && rm -rf "$dir"
|
|
exit $fails
|