@@ -602,7 +602,7 @@ extract_tar_from_url() {
602602 log_info " Extracting $( basename " $tarfile " ) ..."
603603 if tar -xvf " $tarfile " ; then
604604 : > " $markfile " 2> /dev/null || true
605- # Clear the minimal/offline sentinel only if it exists (SC2015-safe)
605+ # Clear the minimal/offline sentinel only if it exists (SC2015-safe)
606606 if [ -f " $skip_sentinel " ]; then
607607 rm -f " $skip_sentinel " 2> /dev/null || true
608608 fi
@@ -706,7 +706,7 @@ weston_stop() {
706706 log_info " Stopping Weston..."
707707 pkill -x weston
708708 for i in $( seq 1 10) ; do
709- log_info " Waiting for Weston to stop with $i attempt "
709+ log_info " Waiting for Weston to stop with $i attempt "
710710 if ! weston_is_running; then
711711 log_info " Weston stopped successfully"
712712 return 0
@@ -3814,3 +3814,143 @@ ensure_network_online() {
38143814 unset net_script_path net_ifaces net_wifi net_ifc net_rc net_had_any_ip
38153815 return 1
38163816}
3817+
3818+ kill_process () {
3819+ TERM_GRACE=" ${KILL_TERM_GRACE:- 3} "
3820+ KILL_GRACE=" ${KILL_KILL_GRACE:- 2} "
3821+ pid_alive () {
3822+ p=" $1 "
3823+ [ -d " /proc/$p " ] || return 1
3824+ st=" $( awk ' {print $3}' " /proc/$p /stat" 2> /dev/null) "
3825+ [ " $st " = " Z" ] && return 1
3826+ return 0
3827+ }
3828+ list_children () {
3829+ p=" $1 "
3830+ if [ -r " /proc/$p /task/$p /children" ]; then
3831+ tr ' \n' ' ' < " /proc/$p /task/$p /children" 2> /dev/null
3832+ return
3833+ fi
3834+ if command -v ps > /dev/null 2>&1 ; then
3835+ ps -o pid= --ppid " $p " 2> /dev/null | tr ' \n' ' '
3836+ fi
3837+ }
3838+ list_descendants () {
3839+ root=" $1 "
3840+ out=" "
3841+ seen=" "
3842+ queue=" $root "
3843+ while [ -n " $queue " ]; do
3844+ next=" "
3845+ for p in $queue ; do
3846+ case " $seen " in * " $p " * ) continue ;; esac
3847+ seen=" $seen$p "
3848+ kids=" $( list_children " $p " ) "
3849+ for c in $kids ; do
3850+ case " $seen " in * " $c " * ) : ;; * )
3851+ out=" $out $c "
3852+ next=" $next $c "
3853+ esac
3854+ done
3855+ done
3856+ queue=" $next "
3857+ done
3858+ printf ' %s\n' " $out " | awk ' NF' | tr ' \n' ' '
3859+ }
3860+ collect_pids_from_pattern () {
3861+ pat=" $1 "
3862+ out=" "
3863+ if command -v pgrep > /dev/null 2>&1 ; then
3864+ out=" $( pgrep -f -- " $pat " 2> /dev/null | tr ' \n' ' ' ) "
3865+ else
3866+ for d in /proc/[0-9]* ; do
3867+ [ -d " $d " ] || continue
3868+ p=" $( basename " $d " ) "
3869+ [ " $p " -eq " $$ " ] && continue
3870+ cmd=" $( tr ' \0' ' ' < " $d /cmdline" 2> /dev/null) "
3871+ [ -n " $cmd " ] || continue
3872+ printf ' %s' " $cmd " | grep -F -- " $pat " > /dev/null 2>&1 && out=" $out $p "
3873+ done
3874+ fi
3875+ for x in $out ; do [ " $x " -ne " $$ " ] && printf ' %s\n' " $x " ; done \
3876+ | awk ' !seen[$0]++' | tr ' \n' ' '
3877+ }
3878+ kill_tree () {
3879+ sig=" $1 " ; p=" $2 "
3880+ [ -n " $p " ] || return 0
3881+ [ " $p " -eq 1 ] && return 0
3882+ [ " $p " -eq " $$ " ] && return 0
3883+ pid_alive " $p " || return 0
3884+ # Try process group (uses pgrp from /proc if available)
3885+ pgrp=" $( awk ' {print $5}' " /proc/$p /stat" 2> /dev/null) "
3886+ [ -n " $pgrp " ] && kill " -$sig " " -$pgrp " 2> /dev/null || true
3887+ all=" $p $( list_descendants " $p " ) "
3888+ for t in $all ; do
3889+ [ " $t " -eq 1 ] && continue
3890+ [ " $t " -eq " $$ " ] && continue
3891+ kill " -$sig " " $t " 2> /dev/null || true
3892+ done
3893+ }
3894+ wait_gone () {
3895+ p=" $1 " ; timeout=" $2 " ; waited=0
3896+ while [ " $waited " -lt " $timeout " ]; do
3897+ pid_alive " $p " || return 0
3898+ sleep 1
3899+ waited=$(( waited+ 1 ))
3900+ done
3901+ return 1
3902+ }
3903+ # -------- Build target set --------
3904+ targets=" "
3905+ if [ " $# " -gt 0 ]; then
3906+ for a in " $@ " ; do
3907+ case " $a " in
3908+ ' ' ) continue ;;
3909+ * [!0-9]* ) pids=" $( collect_pids_from_pattern " $a " ) " ; [ -n " $pids " ] && targets=" $targets $pids " ;;
3910+ * ) targets=" $targets $a " ;;
3911+ esac
3912+ done
3913+ elif [ -n " ${PID:- } " ]; then
3914+ targets=" $PID "
3915+ fi
3916+ if [ -z " $targets " ]; then
3917+ log_warn " kill_process: no targets (neither args nor \$ PID set)."
3918+ return 0
3919+ fi
3920+ # Normalize / de-dup / filter
3921+ uniq=" "
3922+ for t in $targets ; do
3923+ printf ' %s\n' " $t "
3924+ done | awk ' !seen[$0]++' | while IFS= read -r t; do
3925+ printf ' %s' " $t " | grep -Eq ' ^[0-9]+$' || continue
3926+ [ " $t " -eq 1 ] && continue
3927+ [ " $t " -eq " $$ " ] && continue
3928+ if pid_alive " $t " ; then
3929+ uniq=" $uniq $t "
3930+ fi
3931+ done
3932+ targets=" $uniq "
3933+ [ -n " $targets " ] || { log_info " kill_process: nothing running." ; return 0; }
3934+ log_info " Killing process tree(s):$targets "
3935+ rc=0
3936+ for pid in $targets ; do
3937+ kill_tree TERM " $pid "
3938+ if wait_gone " $pid " " $TERM_GRACE " ; then
3939+ log_info " PID $pid terminated with SIGTERM."
3940+ continue
3941+ fi
3942+ log_warn " PID $pid still alive after ${TERM_GRACE} s; escalating to SIGKILL."
3943+ kill_tree KILL " $pid "
3944+ if wait_gone " $pid " " $KILL_GRACE " ; then
3945+ log_info " PID $pid killed with SIGKILL."
3946+ continue
3947+ fi
3948+ if ! pid_alive " $pid " ; then
3949+ log_info " PID $pid no longer running (exited/zombie reaped)."
3950+ continue
3951+ fi
3952+ log_error " PID $pid could not be terminated."
3953+ rc=1
3954+ done
3955+ return " $rc "
3956+ }
0 commit comments