Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions .github/scripts/test_sysupgrade.sh
Original file line number Diff line number Diff line change
Expand Up @@ -4721,6 +4721,26 @@ else
bad "reboot_system must release the watchdog before it reboots (rel=$relw reboot=$rbtw)"
fi

# A boot that never finished: init reads SIGQUIT only after rcS exits, so only
# init's own rcS is ended, and a process merely named like it is left alone.
RB="$SB/rbproc"; rm -rf "$RB"
mkdir -p "$RB/700" "$RB/701" "$RB/702"
printf '/bin/sh\0/etc/init.d/rcS\0' > "$RB/700/cmdline"; printf 'PPid:\t1\n' > "$RB/700/status"
printf '/bin/sh\0/etc/init.d/rcS\0' > "$RB/701/cmdline"; printf 'PPid:\t700\n' > "$RB/701/status"
printf '/bin/sh\0/root/led.sh\0' > "$RB/702/cmdline"; printf 'PPid:\t1\n' > "$RB/702/status"
rb_out=$(WDOG_PROC="$RB" dash -c '
busybox() { shift; echo "KILLED $*"; }
echo_c() { :; }
'"$(sed -n '/^release_boot_scripts()/,/^}/p' "$SRC")"'
release_boot_scripts' 3>/dev/null)
[ "$rb_out" = "KILLED -KILL 700" ] || [ "$rb_out" = "KILLED 700" ] \
&& ok "a stuck boot: only init's own rcS is ended before the hand-off" \
|| bad "release_boot_scripts ended the wrong processes: [$rb_out]"
rm -rf "$RB"
grep -q '^ release_boot_scripts$' "$SRC" \
&& ok "hand_off_pid1 releases the boot scripts before signalling init" \
|| bad "hand_off_pid1 must call release_boot_scripts"

grep -q '^WDOG=${WDOG:-/dev/watchdog}' "$SRC" && grep -q '^WDOG_PROC=${WDOG_PROC:-/proc}' "$SRC" \
&& ok "both watchdog paths are overridable, so this suite never scans the real /proc" \
|| bad "WDOG and WDOG_PROC must be overridable"
Expand Down
24 changes: 23 additions & 1 deletion general/overlay/usr/sbin/sysupgrade
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#!/bin/sh
# OpenIPC.org | 2025
scr_version=1.0.83
scr_version=1.0.84

args="$@"
LOCK_FILE=/tmp/sysupgrade.lock
Expand Down Expand Up @@ -2672,6 +2672,27 @@ stage_handoff() {
[ -x "$RAM_ROOT/sbin/init" ]
}

# Let init get past a boot that never finished.
#
# busybox init looks at its signals only between inittab's stages, and the
# ::sysinit: stage lasts until rcS exits. A foreground loop in /etc/rc.local
# (S99 runs it from rcS) therefore holds SIGQUIT unread for as long as the
# camera is up: the hand-off waits out handoff_wait, reboots with nothing
# written, and every later attempt does the same. init is waiting on rcS's pid
# alone, so ending rcS lets it reach the signal; what rcS left running is killed
# by the hand-off along with everything else.
release_boot_scripts() {
local p cmd
for p in "$WDOG_PROC"/[0-9]*; do
cmd=$(tr '\0' ' ' < "$p/cmdline" 2>&3) || continue
case "$cmd" in *'/etc/init.d/rcS'*) ;; *) continue ;; esac
[ "1" = "$(awk '/^PPid:/ { print $2; exit }' "$p/status" 2>&3)" ] || continue
echo_c 33 "The boot scripts have not finished (often a command in /etc/rc.local running in the foreground), and PID 1 cannot take over until they do: ending them."
busybox kill -KILL "${p##*/}" 2>&3
done
return 0
}

# Hand PID 1 to the ramfs, and never come back.
#
# pivot_root has already moved PID 1's root and cwd here along with ours. What
Expand Down Expand Up @@ -2700,6 +2721,7 @@ hand_off_pid1() {
fi
echo_c 33 "Progress also goes to the serial console. The camera reboots by itself when it is done."
sync
release_boot_scripts
busybox kill -QUIT 1
sleep "${handoff_wait:-30}"
echo_c 31 "PID 1 did not hand over; rebooting (nothing was flashed)"
Expand Down
Loading