#! /bin/sh ## ## Signal handler for runit ## if [ $PPID != 1 ]; then echo "This program should only be invoked by PID 1." # The reason is that killall5 won't kill anything in the same # process group. That means it won't kill your invoking shell, # getty, or svrun. That in turn prevents filesystems from # unmounting, or even being remounted ro, since svrun (at least) has # a FIFO open for writes. And if we reboot without unmounting # filesystems, that's bad. echo "Feel free to read $0 to learn why :)" exit 1 fi waitall () { for i in $(seq 50); do # If all processes are in group 0, we're done awk '($5){exit 1;}' /proc/[0-9]*/stat && return 0 usleep 200000 done return 1 } cleanup () { echo "Stopping services..." sv stop /service/* echo "Asking processes to exit..." killall5 -HUP killall5 -TERM if waitall; then echo "Forcing processes to exit..." killall5 -KILL waitall fi echo "Unmounting file systems..." umount -a -r # Sometimes when we reach here we still haven't been able to umount # everything. Not much more we can do about that, other than flush # write buffers and hope for the best. sync } case $1 in 1) # SIGHUP ;; 15) # SIGTERM: reboot cleanup echo "Rebooting..." reboot -f ;; 10) # SIGUSR1: halt cleanup echo "Halting..." halt -f ;; 12) # SIGUSR2: power cleanup echo "Shutting down..." poweroff -f ;; *) # Everything else ;; esac