freebsd-skq/libexec/rc/rc.d/watchdogd
Andriy Gapon 5fda0d60c1 add ability to set watchdog timeout for a shutdown
This change allows to specify a watchdog(9) timeout for a system
shutdown.  The timeout is activated when the watchdogd daemon is
stopped.  The idea is to a prevent any indefinite hang during late
stages of the shutdown.  The feature is implemented in rc.d/watchdogd,
it builds upon watchdogd -x option.

Note that the shutdown timeout is not actiavted when the watchdogd
service is individually stopped by an operator.  It is also not
activated for the 'shutdown' to the single-user mode.  In those cases it
is assumed that the operator knows what they are doing and they have
means to recover the system should it hang.

Significant subchanges and implementation details:
- the argument to rc.shutdown, completely unused before, is assigned to
  rc_shutdown variable that can be inspected by rc scripts
- init(8) passes "single" or "reboot" as the argument, this is not
  changed
- the argument is not mandatory and if it is not set then rc_shutdown is
  set to "unspecified"
- however, the default jail management scripts and jail configuration
  examples have been updated to pass "jail" to rc.shutdown, just in case
- the new timeout can be set via watchdogd_shutdown_timeout rc option
- for consistency, the regular timeout can now be set via
  watchdogd_timeout rc option
- watchdogd_shutdown_timeout and watchdogd_timeout override timeout
  specifications in watchdogd_flags
- existing configurations, where the new rc options are not set, should
  keep working as before

I am not particularly wed to any of the implementation specifics.
I am open to changing or removing any of them as long as the provided
functionality is the same (or very close) to the proposed one.
For example, I think it can be implemented without using watchdogd -x,
by means of watchdog(1) alone.  In that case there would be a small
window between stopping watchdogd and running watchdog, but I think that
that is acceptable.

Reviewed by:	bcr (man page changes)
MFC after:	5 weeks
Relnotes:	yes
Differential Revision: https://reviews.freebsd.org/D21221
2019-10-03 11:23:10 +00:00

93 lines
2.6 KiB
Bash
Executable File

#!/bin/sh
# Copyright (c) 2003 Sean M. Kelly <smkelly@FreeBSD.org>
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
# 1. Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
# SUCH DAMAGE.
#
# $FreeBSD$
#
# PROVIDE: watchdogd
# REQUIRE: FILESYSTEMS syslogd
# KEYWORD: nojail shutdown
. /etc/rc.subr
name="watchdogd"
desc="Watchdog daemon"
rcvar="watchdogd_enable"
command="/usr/sbin/${name}"
pidfile="/var/run/${name}.pid"
start_precmd="watchdogd_prestart"
stop_precmd="watchdogd_prestop"
stop_postcmd="watchdogd_poststop"
watchdog_command="/usr/sbin/watchdog"
watchdogd_prestart()
{
if [ -n "${watchdogd_timeout}" ] ; then
rc_flags="${rc_flags} -t ${watchdogd_timeout}"
fi
if [ -n "$watchdogd_shutdown_timeout" ] ; then
rc_flags="${rc_flags} -x ${watchdogd_shutdown_timeout}"
fi
return 0
}
watchdogd_prestop()
{
sig_stop="${watchdogd_sig_stop:-TERM}"
}
watchdogd_poststop()
{
if [ ${watchdogd_shutdown_timeout:-0} -gt 0 ] ; then
case "${rc_shutdown}" in
"reboot")
info "watchdog timer is set to" \
${watchdogd_shutdown_timeout} "before shutdown"
return 0
;;
"single")
info "watchdog timer is disabled before going to" \
"single user mode"
${watchdog_command} -t 0
;;
"")
info "watchdog timer is disabled after administrative" \
"${name} stop"
${watchdog_command} -t 0
;;
*)
warn "unknown shutdown mode '${rc_shutdown}'"
warn "watchdog timer is set to ${watchdogd_shutdown_timeout}"
return 0
;;
esac
fi
return 0
}
load_rc_config $name
run_rc_command "$1"