git: 4d1597691916 - main - init: execute /etc/rc.final after all user processes have terminated
Kyle Evans
kevans at FreeBSD.org
Fri Jul 23 04:26:24 UTC 2021
The branch main has been updated by kevans:
URL: https://cgit.FreeBSD.org/src/commit/?id=4d1597691916240b9023ee9f15e249503abf67fd
commit 4d1597691916240b9023ee9f15e249503abf67fd
Author: Kyle Evans <kevans at FreeBSD.org>
AuthorDate: 2021-07-20 10:40:30 +0000
Commit: Kyle Evans <kevans at FreeBSD.org>
CommitDate: 2021-07-23 04:26:11 +0000
init: execute /etc/rc.final after all user processes have terminated
This can be useful for, e.g., unmounting filesystems that were needed
for shutdown.
Reviewed by: kib
Sponsored by: NetApp, Inc.
Sponsored by: Klara, Inc.
X-NetApp-PR: #63
Differential Revision: https://reviews.freebsd.org/D31230
---
sbin/init/init.8 | 17 ++++++++++++++---
sbin/init/init.c | 51 +++++++++++++++++++++++++++++++++++++++++++++++++++
sbin/init/pathnames.h | 1 +
3 files changed, 66 insertions(+), 3 deletions(-)
diff --git a/sbin/init/init.8 b/sbin/init/init.8
index d852c32ef487..9475b1cce48f 100644
--- a/sbin/init/init.8
+++ b/sbin/init/init.8
@@ -31,7 +31,7 @@
.\" @(#)init.8 8.3 (Berkeley) 4/18/94
.\" $FreeBSD$
.\"
-.Dd August 6, 2019
+.Dd July 22, 2021
.Dt INIT 8
.Os
.Sh NAME
@@ -279,6 +279,14 @@ Otherwise,
.Dq Li reboot
argument is used.
.Pp
+After all user processes have been terminated,
+.Nm
+will try to run the
+.Pa /etc/rc.final
+script.
+This script can be used to finally prepare and unmount filesystems that may have
+been needed during shutdown, for instance.
+.Pp
The role of
.Nm
is so critical that if it dies, the system will reboot itself
@@ -371,9 +379,10 @@ It is used for running the
or
.Va init_script
if set, as well as for the
-.Pa /etc/rc
+.Pa /etc/rc ,
+.Pa /etc/rc.shutdown ,
and
-.Pa /etc/rc.shutdown
+.Pa /etc/rc.final
scripts.
The value of the corresponding
.Xr kenv 2
@@ -403,6 +412,8 @@ the terminal initialization information file
system startup commands
.It Pa /etc/rc.shutdown
system shutdown commands
+.It Pa /etc/rc.final
+system shutdown commands (after process termination)
.It Pa /var/log/init.log
log of
.Xr rc 8
diff --git a/sbin/init/init.c b/sbin/init/init.c
index 943db9f26bd3..230c141bd351 100644
--- a/sbin/init/init.c
+++ b/sbin/init/init.c
@@ -109,6 +109,7 @@ static void disaster(int);
static void revoke_ttys(void);
static int runshutdown(void);
static char *strk(char *);
+static void runfinal(void);
/*
* We really need a recursive typedef...
@@ -876,6 +877,8 @@ single_user(void)
if (Reboot) {
/* Instead of going single user, let's reboot the machine */
sync();
+ /* Run scripts after all processes have been terminated. */
+ runfinal();
if (reboot(howto) == -1) {
emergency("reboot(%#x) failed, %m", howto);
_exit(1); /* panic and reboot */
@@ -2039,3 +2042,51 @@ setprocresources(const char *cname)
}
}
#endif
+
+/*
+ * Run /etc/rc.final to execute scripts after all user processes have been
+ * terminated.
+ */
+static void
+runfinal(void)
+{
+ struct stat sb;
+ pid_t other_pid, pid;
+ sigset_t mask;
+
+ /* Avoid any surprises. */
+ alarm(0);
+
+ /* rc.final is optional. */
+ if (stat(_PATH_RUNFINAL, &sb) == -1 && errno == ENOENT)
+ return;
+ if (access(_PATH_RUNFINAL, X_OK) != 0) {
+ warning("%s exists, but not executable", _PATH_RUNFINAL);
+ return;
+ }
+
+ pid = fork();
+ if (pid == 0) {
+ /*
+ * Reopen stdin/stdout/stderr so that scripts can write to
+ * console.
+ */
+ close(0);
+ open(_PATH_DEVNULL, O_RDONLY);
+ close(1);
+ close(2);
+ open_console();
+ dup2(1, 2);
+ sigemptyset(&mask);
+ sigprocmask(SIG_SETMASK, &mask, NULL);
+ signal(SIGCHLD, SIG_DFL);
+ execl(_PATH_RUNFINAL, _PATH_RUNFINAL, NULL);
+ perror("execl(" _PATH_RUNFINAL ") failed");
+ exit(1);
+ }
+
+ /* Wait for rc.final script to exit */
+ while ((other_pid = waitpid(-1, NULL, 0)) != pid && other_pid > 0) {
+ continue;
+ }
+}
diff --git a/sbin/init/pathnames.h b/sbin/init/pathnames.h
index 2ed366e4f7f7..7dc75ba52491 100644
--- a/sbin/init/pathnames.h
+++ b/sbin/init/pathnames.h
@@ -41,5 +41,6 @@
#define _PATH_SLOGGER "/sbin/session_logger"
#define _PATH_RUNCOM "/etc/rc"
#define _PATH_RUNDOWN "/etc/rc.shutdown"
+#define _PATH_RUNFINAL "/etc/rc.final"
#define _PATH_REROOT "/dev/reroot"
#define _PATH_REROOT_INIT _PATH_REROOT "/init"
More information about the dev-commits-src-all
mailing list