Download scripts/stop_h2_policy_eval.sh from BAAI/PingPongRealWorldRL: direct link, hf CLI and curl.
- Browser
- Download file 5.89 kB
-
https://huggingface.co/BAAI/PingPongRealWorldRL/resolve/main/scripts/stop_h2_policy_eval.sh
- Command line
-
hf download hf://BAAI/PingPongRealWorldRL/scripts/stop_h2_policy_eval.sh
-
curl -L -o stop_h2_policy_eval.sh https://huggingface.co/BAAI/PingPongRealWorldRL/resolve/main/scripts/stop_h2_policy_eval.sh
5.89 kB
| # Graceful, project-owned evaluation stop. Never sends R1 or motor commands. | |
| set -euo pipefail | |
| PROJECT_ROOT=$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")/.." && pwd -P) | |
| RUN_DIR= | |
| ACK= | |
| ABORTED=0 | |
| usage() { | |
| echo 'Usage: bash scripts/stop_h2_policy_eval.sh [--run-dir PATH] --ack-r1 H2-R1-CONFIRMED' | |
| echo ' or: --ack-hardware-off H2-HARDWARE-POWER-OFF-CONFIRMED' | |
| echo ' or: --startup-aborted (only when runner never started)' | |
| } | |
| fail() { echo "$*" >&2; exit 1; } | |
| while (($#)); do | |
| case "$1" in | |
| --run-dir) RUN_DIR=${2:?missing run directory}; shift 2 ;; | |
| --ack-r1|--ack-hardware-off) ACK=${2:?missing acknowledgement}; shift 2 ;; | |
| --startup-aborted) ABORTED=1; shift ;; | |
| -h|--help) usage; exit 0 ;; | |
| *) usage >&2; exit 2 ;; | |
| esac | |
| done | |
| if [[ -z $RUN_DIR ]]; then | |
| [[ -f "$PROJECT_ROOT/artifacts/latest_eval_run" ]] || fail 'No evaluation run pointer in this project.' | |
| IFS= read -r RUN_DIR < "$PROJECT_ROOT/artifacts/latest_eval_run" | |
| fi | |
| [[ -d $RUN_DIR ]] || fail "Evaluation run directory does not exist: $RUN_DIR" | |
| RUN_DIR=$(cd -- "$RUN_DIR" && pwd -P) | |
| H2_ROOT= | |
| H2_IF= | |
| H2_PY= | |
| H2_SESSION= | |
| FB_SESSION= | |
| H2_EVAL_RUN_DIR= | |
| if [[ -f "$RUN_DIR/eval_owner.env" ]]; then | |
| source "$RUN_DIR/eval_owner.env" | |
| elif [[ -f "$RUN_DIR/run.env" ]]; then | |
| source "$RUN_DIR/run.env" | |
| else | |
| fail 'Missing evaluation owner metadata; nothing stopped.' | |
| fi | |
| [[ -n $H2_ROOT && -d $H2_ROOT ]] || fail 'Missing evaluation project owner; nothing stopped.' | |
| [[ $(cd -- "$H2_ROOT" && pwd -P) == "$PROJECT_ROOT" ]] \ | |
| || fail 'Evaluation run belongs to another project; nothing stopped.' | |
| SESSION=${H2_SESSION:-$FB_SESSION} | |
| [[ $SESSION =~ ^[A-Za-z0-9_.-]+$ ]] || fail 'Invalid evaluation session owner; nothing stopped.' | |
| SCORES=${H2_EVAL_RUN_DIR:-$RUN_DIR/evaluation} | |
| has_session() { tmux has-session -t "=$SESSION" 2>/dev/null; } | |
| if has_session; then | |
| # show-options uses target-pane syntax; ':' keeps the exact session scope. | |
| [[ $(tmux show-options -v -t "=$SESSION:" @h2_eval_run_dir) == "$RUN_DIR" ]] \ | |
| || fail 'Evaluation tmux owner mismatch; nothing stopped.' | |
| elif [[ -f "$RUN_DIR/eval.stopped" ]]; then | |
| echo "Evaluation already stopped. Scores: $SCORES" | |
| exit 0 | |
| fi | |
| [[ -f "$RUN_DIR/panes.tsv" ]] || fail 'Missing stable evaluation pane ownership; nothing stopped.' | |
| pane_info() { | |
| tmux display-message -p -t "$1" '#{session_name} #{pane_id} #{pane_dead}' 2>/dev/null || true | |
| } | |
| check_pane() { | |
| local pane=$1 info | |
| [[ $pane =~ ^%[0-9]+$ ]] || fail 'Invalid evaluation pane id; nothing stopped.' | |
| info=$(pane_info "$pane") | |
| [[ -z $info || $info == "$SESSION $pane 0" || $info == "$SESSION $pane 1" ]] \ | |
| || fail "Pane $pane belongs to another session; nothing stopped." | |
| } | |
| while IFS=$'\t' read -r role pane; do | |
| [[ -n $role ]] || continue | |
| case "$role" in | |
| control|runner|predictor|planner|adapter|monitor|bridge) check_pane "$pane" ;; | |
| *) fail "Unknown evaluation pane role: $role; nothing stopped." ;; | |
| esac | |
| done < "$RUN_DIR/panes.tsv" | |
| if [[ $ABORTED == 1 ]]; then | |
| [[ ! -e "$RUN_DIR/runner.started" ]] || fail 'Runner started; use confirmed R1 or power-off before stop.' | |
| elif [[ $ACK == H2-R1-CONFIRMED ]]; then | |
| [[ -n $H2_PY ]] || fail 'Missing evaluation Python; nothing stopped.' | |
| ( | |
| cd -- "$PROJECT_ROOT" | |
| "$H2_PY" - <<'PY' | |
| from runtime.h2_shm_bridge import H2SharedMemoryBridge | |
| bridge = H2SharedMemoryBridge(claim_writer=False, independent_reader=True) | |
| try: | |
| state = bridge.read_state() | |
| if not (state.stop_requested and state.emergency_stop): | |
| raise SystemExit("R1 stop/fault is not latched; no process was stopped") | |
| print("Verified stop=1 fault=1; read-only, no policy model loaded") | |
| finally: | |
| bridge.close() | |
| PY | |
| ) | |
| elif [[ $ACK != H2-HARDWARE-POWER-OFF-CONFIRMED ]]; then | |
| usage >&2 | |
| fail 'Operator R1 or confirmed physical power-off is required; nothing stopped.' | |
| fi | |
| # Serialize only the launch decision, never worker exit or journal flush. | |
| ( | |
| flock -x 9 | |
| touch "$RUN_DIR/eval.stop" | |
| if [[ $ABORTED == 1 && -e "$RUN_DIR/runner.started" ]]; then | |
| fail 'Runner started while cancelling startup; session preserved. Confirm R1 or power-off, then retry.' | |
| fi | |
| ) 9>"$RUN_DIR/eval.lifecycle.lock" | |
| role_pane() { awk -F '\t' -v role="$1" '$1 == role {print $2; exit}' "$RUN_DIR/panes.tsv"; } | |
| control=$(role_pane control) | |
| if [[ -n $control ]]; then | |
| check_pane "$control" | |
| if [[ $(pane_info "$control") == "$SESSION $control 0" ]]; then | |
| tmux send-keys -t "$control" C-c 2>/dev/null || true | |
| fi | |
| fi | |
| # A launcher already entering RUNNER must not be mistaken for an aborted start. | |
| if [[ $ABORTED == 1 && -e "$RUN_DIR/runner.started" ]]; then | |
| fail 'Runner started while cancelling startup; session preserved. Confirm R1 or power-off, then retry.' | |
| fi | |
| stop_role() { | |
| local role=$1 pane info | |
| pane=$(role_pane "$role") | |
| [[ -n $pane ]] || return 0 | |
| check_pane "$pane" | |
| info=$(pane_info "$pane") | |
| [[ $info == "$SESSION $pane 0" ]] || return 0 | |
| tmux send-keys -t "$pane" C-c 2>/dev/null || true | |
| for _ in {1..60}; do | |
| info=$(pane_info "$pane") | |
| [[ -z $info || $info == "$SESSION $pane 1" ]] && return 0 | |
| [[ $info == "$SESSION $pane 0" ]] || fail "Pane $pane ownership changed; session preserved." | |
| sleep 0.5 | |
| done | |
| fail "$role did not exit within 30 seconds; session preserved. Wait for journal flush and retry; no force kill." | |
| } | |
| for role in runner predictor planner adapter monitor bridge; do | |
| stop_role "$role" | |
| done | |
| if has_session; then | |
| tmux kill-session -t "=$SESSION" || { | |
| ! has_session || fail 'Owned session could not be closed; it was not force-killed.' | |
| } | |
| fi | |
| touch "$RUN_DIR/eval.stopped" | |
| if [[ -e /dev/shm/h2_pingpong_bridge ]]; then | |
| echo 'WARNING: /dev/shm/h2_pingpong_bridge still exists; retained, not deleted.' >&2 | |
| fi | |
| echo "Stopped only evaluation session $SESSION. Scores: $SCORES" | |
| echo 'Shared capture, other projects and network configuration were not changed.' | |