153 lines
3.8 KiB
Bash
Executable File
153 lines
3.8 KiB
Bash
Executable File
#! /bin/sh
|
|
### BEGIN INIT INFO
|
|
# Provides: sendsigs
|
|
# Required-Start:
|
|
# Required-Stop: umountnfs
|
|
# Default-Start:
|
|
# Default-Stop: 0 6
|
|
# Short-Description: Kill all remaining processes.
|
|
# Description:
|
|
### END INIT INFO
|
|
|
|
PATH=/sbin:/usr/sbin:/bin:/usr/bin
|
|
|
|
. /lib/lsb/init-functions
|
|
|
|
# Make it possible to see who the misbehaving processes are
|
|
report_unkillable() {
|
|
[ -x /usr/share/apport/unkillable_shutdown ] || return
|
|
if [ ! -e /etc/default/apport ] || ! grep -q '^enabled[[:space:]]*=[[:space:]]*1' /etc/default/apport; then
|
|
return
|
|
fi
|
|
/usr/share/apport/unkillable_shutdown $OMITPIDS
|
|
}
|
|
|
|
upstart_killed_jobs () {
|
|
initctl list | grep 'stop/killed'
|
|
}
|
|
|
|
upstart_jobs () {
|
|
initctl list | grep -E '(start/|stop/killed)' | sed -n -e "/process [0-9]/s/.*process //p"
|
|
}
|
|
|
|
do_stop () {
|
|
OMITPIDS=
|
|
|
|
for omitfile in /run/sendsigs.omit; do
|
|
if [ -e $omitfile ]; then
|
|
for pid in $(cat $omitfile); do
|
|
OMITPIDS="${OMITPIDS:+$OMITPIDS }-o $pid"
|
|
done
|
|
fi
|
|
done
|
|
|
|
# Load sendsigs.omit.d/packagename files too, to make it
|
|
# possible for scripts that need to modify the list of pids at
|
|
# run time without race conditions.
|
|
for omitdir in /run/sendsigs.omit.d; do
|
|
if [ -d "${omitdir}" ]; then
|
|
for pidfile in "${omitdir}/"*; do
|
|
[ -f "$pidfile" ] || continue
|
|
for pid in $(cat $pidfile); do
|
|
OMITPIDS="${OMITPIDS:+$OMITPIDS }-o $pid"
|
|
done
|
|
done
|
|
fi
|
|
done
|
|
|
|
# Upstart jobs have their own "stop on" clauses that sends
|
|
# SIGTERM/SIGKILL just like this, so if they're still running,
|
|
# they're supposed to be
|
|
if [ -x /sbin/initctl ]; then
|
|
for pid in $(upstart_jobs); do
|
|
OMITPIDS="${OMITPIDS:+$OMITPIDS }-o $pid"
|
|
done
|
|
fi
|
|
|
|
# Flush the kernel I/O buffer before we start to kill
|
|
# processes, to make sure the IO of already stopped services to
|
|
# not slow down the remaining processes to a point where they
|
|
# are accidentily killed with SIGKILL because they did not
|
|
# manage to shut down in time.
|
|
sync
|
|
|
|
# Kill all processes.
|
|
log_action_begin_msg "Asking all remaining processes to terminate"
|
|
killall5 -15 $OMITPIDS # SIGTERM
|
|
log_action_end_msg 0
|
|
alldead=""
|
|
OMITPIDS0="$OMITPIDS"
|
|
for seq in 1 2 3 4 5 6 7 8 9 10; do
|
|
OMITPIDS="$OMITPIDS0"
|
|
# use SIGCONT/signal 18 to check if there are
|
|
# processes left. No need to check the exit code
|
|
# value, because either killall5 work and it make
|
|
# sense to wait for processes to die, or it fail and
|
|
# there is nothing to wait for.
|
|
|
|
# did an upstart job start since we last polled initctl? check
|
|
# again on each loop and add any new jobs (e.g., plymouth) to
|
|
# the list. If we did miss one starting up, this beats waiting
|
|
# 10 seconds before shutting down.
|
|
if [ -x /sbin/initctl ]; then
|
|
for pid in $(upstart_jobs); do
|
|
OMITPIDS="${OMITPIDS:+$OMITPIDS }-o $pid"
|
|
done
|
|
fi
|
|
if killall5 -18 $OMITPIDS ; then
|
|
:
|
|
else
|
|
alldead=1
|
|
break
|
|
fi
|
|
|
|
sleep 1
|
|
done
|
|
|
|
# Upstart has a method to set a kill timeout and so the job author
|
|
# may want us to wait longer than 10 seconds (as in the case of
|
|
# mysql). (LP: #688541)
|
|
#
|
|
# We will wait up to 300 seconds for any jobs in stop/killed state.
|
|
# Any kill timeout higher than that will be overridden by the need
|
|
# to shutdown. NOTE the re-use of seq from above, since we already
|
|
# waited up to 10 seconds for them.
|
|
while [ -n "$(upstart_killed_jobs)" ] ; do
|
|
seq=$(($seq+1))
|
|
if [ $seq -ge 300 ] ; then
|
|
break
|
|
fi
|
|
|
|
sleep 1
|
|
done
|
|
|
|
if [ -z "$alldead" ] ; then
|
|
#report_unkillable
|
|
log_action_begin_msg "Killing all remaining processes"
|
|
killall5 -9 $OMITPIDS # SIGKILL
|
|
log_action_end_msg 1
|
|
else
|
|
log_action_begin_msg "All processes ended within $seq seconds"
|
|
log_action_end_msg 0
|
|
fi
|
|
}
|
|
|
|
case "$1" in
|
|
start|status)
|
|
# No-op
|
|
;;
|
|
restart|reload|force-reload)
|
|
echo "Error: argument '$1' not supported" >&2
|
|
exit 3
|
|
;;
|
|
stop)
|
|
do_stop
|
|
;;
|
|
*)
|
|
echo "Usage: $0 start|stop" >&2
|
|
exit 3
|
|
;;
|
|
esac
|
|
|
|
:
|