git: a45048565a1c - main - bsdinstall: Fix race condition when shutting down after installation

From: Jessica Clarke <jrtc27_at_FreeBSD.org>
Date: Thu, 06 Oct 2022 19:25:18 UTC
The branch main has been updated by jrtc27:

URL: https://cgit.FreeBSD.org/src/commit/?id=a45048565a1cb4aec118a941237b00da83d56530

commit a45048565a1cb4aec118a941237b00da83d56530
Author:     Jessica Clarke <jrtc27@FreeBSD.org>
AuthorDate: 2022-10-06 19:04:04 +0000
Commit:     Jessica Clarke <jrtc27@FreeBSD.org>
CommitDate: 2022-10-06 19:04:04 +0000

    bsdinstall: Fix race condition when shutting down after installation
    
    Whilst reboot(8) will block whilst it runs, shutdown(8) does not,
    daemonizing instead. This means that we must wait after running it,
    otherwise we will exit and cause the system to attempt to go multi-user
    in parallel with the shutdown daemon killing init. With the new
    multi-console support in the installer, runconsoles will immediately
    kill this daemon, racing with the daemon being able to signal init as
    desired, and I have seen this race be lost in QEMU with a single CPU. In
    the past this wasn't such an issue, since shutdown's daemon puts itself
    in a new session group immediately after fork (and the parent doesn't
    wait until that has happened, so whilst there's technically a race
    condition in there where it could receive a SIGHUP from the death of the
    parent's session leader, in practice this is very unlikely to be hit.
    This means that the only consequence of this oversight before was that
    you might get the beginnings of more console output on the way to
    multi-user and thus the console would look a little confusing.
    
    Reviewed by:    gjb
    Fixes:          e4505364c087 ("release/rc.local: Provide option to shutdown after installation complete")
    Fixes:          a09af1b7fd95 ("bsdinstall release: Start installer on multiple consoles")
    Differential Revision:  https://reviews.freebsd.org/D36879
---
 usr.sbin/bsdinstall/startbsdinstall | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/usr.sbin/bsdinstall/startbsdinstall b/usr.sbin/bsdinstall/startbsdinstall
index 0a8207df9bd8..af0fd56e73b3 100644
--- a/usr.sbin/bsdinstall/startbsdinstall
+++ b/usr.sbin/bsdinstall/startbsdinstall
@@ -78,6 +78,17 @@ $BSDDIALOG_OK)	# Install
 			;;
 		$BSDDIALOG_EXTRA)	# Shutdown
 			shutdown -p now
+			# shutdown(8) daemonizes, with the actual signal to
+			# init(8) happening in the child, but if we exit the
+			# script then runconsoles will clean up its children
+			# thinking we're trying to go multiuser (and if the
+			# user has disabled multiple console support we'll
+			# still start trying to go multi-user, which gives
+			# confusing output on the console if the daemon is slow
+			# to run). Thus we spin while the daemon runs.
+			while true; do
+				sleep 1
+			done
 			;;
 		$BSDDIALOG_CANCEL)	# Live CD
 			exit 0