aboutsummaryrefslogtreecommitdiff
path: root/libexec/rc
diff options
context:
space:
mode:
authorAndriy Gapon <avg@FreeBSD.org>2019-10-03 11:23:10 +0000
committerAndriy Gapon <avg@FreeBSD.org>2019-10-03 11:23:10 +0000
commit5fda0d60c1e004d6581f29c006635a51cee81349 (patch)
treed34df51e7400ed88881410b751d1154929f0f48b /libexec/rc
parent912c3fe7157d22ee244e266c017287242cd8081c (diff)
downloadsrc-5fda0d60c1e004d6581f29c006635a51cee81349.tar.gz
src-5fda0d60c1e004d6581f29c006635a51cee81349.zip
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
Notes
Notes: svn path=/head/; revision=353039
Diffstat (limited to 'libexec/rc')
-rw-r--r--libexec/rc/rc.conf4
-rwxr-xr-xlibexec/rc/rc.d/jail2
-rwxr-xr-xlibexec/rc/rc.d/watchdogd50
-rw-r--r--libexec/rc/rc.shutdown2
4 files changed, 55 insertions, 3 deletions
diff --git a/libexec/rc/rc.conf b/libexec/rc/rc.conf
index 017ae6484f0f..e60ddda369cd 100644
--- a/libexec/rc/rc.conf
+++ b/libexec/rc/rc.conf
@@ -679,6 +679,10 @@ harvest_mask="511" # Entropy device harvests all but the very invasive sources.
dmesg_enable="YES" # Save dmesg(8) to /var/run/dmesg.boot
watchdogd_enable="NO" # Start the software watchdog daemon
watchdogd_flags="" # Flags to watchdogd (if enabled)
+watchdogd_timeout="" # watchdogd timeout, overrides -t in watchdogd_flags
+watchdogd_shutdown_timeout="" # Timeout to use after watchdogd is stopped.
+ # Has effect only for system shutdown.
+ # Overrides -x in watchdogd_flags.
devfs_rulesets="/etc/defaults/devfs.rules /etc/devfs.rules" # Files containing
# devfs(8) rules.
devfs_system_ruleset="" # The name (NOT number) of a ruleset to apply to /dev
diff --git a/libexec/rc/rc.d/jail b/libexec/rc/rc.d/jail
index 4a5213e309d4..1a3b551c9a4c 100755
--- a/libexec/rc/rc.d/jail
+++ b/libexec/rc/rc.d/jail
@@ -168,7 +168,7 @@ parse_options()
if [ -z "${_exec_start}" ]; then
_exec_start="/bin/sh /etc/rc"
if [ -z "${_exec_stop}" ]; then
- _exec_stop="/bin/sh /etc/rc.shutdown"
+ _exec_stop="/bin/sh /etc/rc.shutdown jail"
fi
fi
fi
diff --git a/libexec/rc/rc.d/watchdogd b/libexec/rc/rc.d/watchdogd
index 1de2d9319280..b48696cc8504 100755
--- a/libexec/rc/rc.d/watchdogd
+++ b/libexec/rc/rc.d/watchdogd
@@ -38,9 +38,55 @@ 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"
-load_rc_config $name
+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}"
+}
-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"
diff --git a/libexec/rc/rc.shutdown b/libexec/rc/rc.shutdown
index 15779c784091..0f60ffbad9cc 100644
--- a/libexec/rc/rc.shutdown
+++ b/libexec/rc/rc.shutdown
@@ -43,6 +43,8 @@ HOME=/
PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/sbin
export HOME PATH
+rc_shutdown=${1:-"unspecified"}
+
. /etc/rc.subr
load_rc_config