The branch main has been updated by kevans:

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

commit 4d1597691916240b9023ee9f15e249503abf67fd
Author:     Kyle Evans <kev...@freebsd.org>
AuthorDate: 2021-07-20 10:40:30 +0000
Commit:     Kyle Evans <kev...@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"
_______________________________________________
dev-commits-src-main@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/dev-commits-src-main
To unsubscribe, send any mail to "dev-commits-src-main-unsubscr...@freebsd.org"

Reply via email to