diagnose native Recovery disk IPC with bounded observation

This commit is contained in:
dh
2026-10-04 08:41:06 +02:00
parent 94a70b2005
commit 25989cf0eb
4 changed files with 125 additions and 5 deletions
+93 -1
View File
@@ -14,6 +14,9 @@ TIMER_FIFO="/tmp/native-diagnostic-$PROOF_TOKEN-$$.fifo"
PENDING_OUTPUTS=()
ACTIVE_COMMAND=""
ACTIVE_TIMER=""
# BEGIN disk IPC diagnostic
ACTIVE_OBSERVER=""
# END disk IPC diagnostic
os_version=""
architecture=""
uid=-1
@@ -96,8 +99,75 @@ read_scalar() {
SCALAR="$value"
}
# BEGIN disk IPC diagnostic
# Optional observations have their own child/timer ownership. No service is
# loaded, restarted or changed, and samples target only this probe's diskutil.
observe_disk_query() {
local disk_process="$1" output="$2" sample_output="$3" observation_child="" observation_timer=""
cancel_observation() {
trap '' TERM INT
if [ -n "$observation_child" ]; then
kill -TERM "$observation_child" 2>/dev/null || :
IFS= read -r -t 2 -u 9 unused || :
kill -KILL "$observation_child" 2>/dev/null || :
wait "$observation_child" 2>/dev/null || :
fi
[ -z "$observation_timer" ] || { kill -TERM "$observation_timer" 2>/dev/null || :; wait "$observation_timer" 2>/dev/null || :; }
printf '[disk-observation] stopped after the owned disk query\n' >> "$output"
exit 143
}
observe_command() {
local name="$1" status started=$SECONDS
shift
printf '\n[disk-observation-command] %s:' "$name" >> "$output"
printf ' %s' "$@" >> "$output"
printf '\n' >> "$output"
"$@" >> "$output" 2>&1 &
observation_child=$!
(
trap 'exit 0' TERM INT
IFS= read -r -t 8 -u 9 unused || :
printf '[disk-observation-timeout] %s child=%s limit=8s\n' "$name" "$observation_child" >> "$output"
kill -TERM "$observation_child" 2>/dev/null || :
IFS= read -r -t 2 -u 9 unused || :
kill -KILL "$observation_child" 2>/dev/null || :
) &
observation_timer=$!
wait "$observation_child"; status=$?
kill -TERM "$observation_timer" 2>/dev/null || :
wait "$observation_timer" 2>/dev/null || :
printf '[disk-observation-exit] %s status=%s elapsed=%ss\n' "$name" "$status" "$((SECONDS - started))" >> "$output"
observation_child=""; observation_timer=""
}
trap cancel_observation TERM INT
printf '[disk-observation] owned-diskutil-child=%s parent-shell=%s\n' "$disk_process" "$$" >> "$output"
observe_command processes /bin/ps -axo pid,ppid,state,comm
if [ -x /usr/bin/sample ]; then
if kill -0 "$disk_process" 2>/dev/null; then
observe_command diskutil-sample /usr/bin/sample "$disk_process" 3 10 -file "$sample_output"
else
printf '[disk-observation-unavailable] diskutil already exited before sample\n' >> "$output"
fi
else
printf '[disk-observation-unavailable] /usr/bin/sample is unavailable\n' >> "$output"
fi
observe_command arbitration /bin/launchctl print system/com.apple.diskarbitrationd
observe_command management /bin/launchctl print system/com.apple.diskmanagementd
}
stop_disk_observation() {
[ -n "$ACTIVE_OBSERVER" ] || return 0
kill -TERM "$ACTIVE_OBSERVER" 2>/dev/null || :
wait "$ACTIVE_OBSERVER" 2>/dev/null || :
ACTIVE_OBSERVER=""
}
# END disk IPC diagnostic
cancel_probe() {
trap '' TERM INT
# BEGIN disk IPC diagnostic
stop_disk_observation
# END disk IPC diagnostic
if [ -n "$ACTIVE_COMMAND" ]; then
kill -TERM "$ACTIVE_COMMAND" 2>/dev/null || :
IFS= read -r -t 2 -u 9 unused || :
@@ -136,6 +206,18 @@ run_command() {
) &
timer=$!
ACTIVE_TIMER="$timer"
# BEGIN disk IPC diagnostic
if [[ "$name" == disks && "$attempt" == 1 ]]; then
local observation_output="/tmp/native-diagnostic-disk-observation.out"
local sample_output="/tmp/native-diagnostic-disk-sample.out"
: > "$observation_output"
: > "$sample_output"
observe_disk_query "$process" "$observation_output" "$sample_output" &
ACTIVE_OBSERVER=$!
printf '[disk-observation-start] observer=%s owned-diskutil-child=%s\n' "$ACTIVE_OBSERVER" "$process" >&3
PENDING_OUTPUTS+=("$observation_output" "$sample_output")
fi
# END disk IPC diagnostic
wait "$process"
exit_code=$?
waited=$SECONDS
@@ -143,6 +225,9 @@ run_command() {
printf '[proof-native-wait] %s child=%s elapsed=%ss exit=%s\n' "$name" "$process" "$((waited - started))" "$exit_code" >&3
kill -TERM "$timer" 2>/dev/null || :
wait "$timer" 2>/dev/null || :
# BEGIN disk IPC diagnostic
stop_disk_observation
# END disk IPC diagnostic
ACTIVE_COMMAND=""; ACTIVE_TIMER=""
printf '[proof-cleanup] %s child=%s elapsed=%ss total=%ss\n' "$name" "$process" "$((SECONDS - waited))" "$((SECONDS - started))" >&3
printf '[proof-exit] %s\n' "$exit_code" >&3
@@ -203,10 +288,17 @@ os_version="$SCALAR"
(( ${os_version%%.*} >= 13 )) || fail_probe unsupported_macos_version
flush_outputs || finish false diagnostic_log_budget_exceeded
# BEGIN disk IPC diagnostic
run_command arbitration_before /bin/launchctl print system/com.apple.diskarbitrationd
run_command management_before /bin/launchctl print system/com.apple.diskmanagementd
run_command media_before /usr/sbin/ioreg -r -c IOMedia -l -w 0
flush_outputs || finish false diagnostic_log_budget_exceeded
# END disk IPC diagnostic
# Bound readiness independently of the host's 40-minute overall deadline.
readiness_start=$SECONDS
attempt=0
while (( SECONDS - readiness_start < 600 )); do
while (( attempt < 2 && SECONDS - readiness_start < 600 )); do
attempt=$((attempt + 1))
printf '\n[readiness-attempt] %s\n' "$attempt" >&3
run_command disks /usr/sbin/diskutil list physical