Date: Thu, 22 Dec 1994 15:15:11 +0100 (MET) From: roberto@blaise.ibp.fr (Ollivier ROBERT) To: hackers@freebsd.org (Hackers' list FreeBSD) Subject: /etc/rc.shutdown (First shot) Message-ID: <9412221415.AA02591@blaise.ibp.fr>
next in thread | raw e-mail | index | archive | help
Hello,
I've tried to implement a /etc/rc.shutdown mechanism into init. Can someone
review the following patch and find any errors I could have made ? I cannot
test it at the moment...
Don't worry it is not a full blown /etc/rc0.d :-)
===================================================================
RCS file: /build/master/freebsd/init/init.8,v
retrieving revision 1.2
diff -u -r1.2 init.8
--- 1.2 1994/08/27 21:32:01
+++ init.8 1994/12/22 14:02:33
@@ -238,6 +238,15 @@
This is useful for shutting the machine down cleanly from inside the kernel
or from X when the machines appears to be hung.
.Pp
+When shuting down the machine,
+.Nm init
+will try to run the
+.Pa /etc/rc.shutdown
+script. This script can be used to cleanly terminate specific programs such
+as
+.Nm innd
+(the InterNetNews server).
+.Pp
The role of
.Nm init
is so critical that if it dies, the system will reboot itself
@@ -277,6 +286,8 @@
The terminal initialization information file.
.It Pa /etc/rc
System startup commands.
+.It Pa /etc/rc.shutdown
+System shutdown commands.
.El
.Sh SEE ALSO
.Xr login 1 ,
===================================================================
RCS file: /build/master/freebsd/init/init.c,v
retrieving revision 1.5
diff -u -r1.5 init.c
--- 1.5 1994/10/14 17:15:40
+++ init.c 1994/12/22 14:03:23
@@ -98,6 +98,7 @@
void emergency __P((char *, ...));
void disaster __P((int));
void badsys __P((int));
+int runshutdown __P((void));
/*
* We really need a recursive typedef...
@@ -1349,6 +1350,7 @@
death()
{
register session_t *sp;
+ register int rcdown;
register int i;
pid_t pid;
static const int death_sigs[3] = { SIGHUP, SIGTERM, SIGKILL };
@@ -1356,6 +1358,11 @@
for (sp = sessions; sp; sp = sp->se_next)
sp->se_flags |= SE_SHUTDOWN;
+ /* Try to run the rc.shutdown script */
+ rcdown = runshutdown();
+ if (rcdown)
+ stall("Could not run %s, check this please.", _PATH_RUNDOWN);
+
/* NB: should send a message to the session logger to avoid blocking. */
logwtmp("~", "shutdown", "");
@@ -1377,4 +1384,90 @@
warning("some processes would not die; ps axl advised");
return (state_func_t) single_user;
+}
+
+/*
+ * Run the system shutdown script.
+ *
+ * Exit codes: XXX I should document more
+ * 0 good.
+ * 1 fatal error
+ * 2 some error
+ */
+int
+runshutdown()
+{
+ pid_t pid, wpid;
+ int status;
+ char *argv[3];
+ struct sigaction sa;
+
+ if ((pid = fork()) == 0) {
+ sigemptyset(&sa.sa_mask);
+ sa.sa_flags = 0;
+ sa.sa_handler = SIG_IGN;
+ (void) sigaction(SIGTSTP, &sa, (struct sigaction *)0);
+ (void) sigaction(SIGHUP, &sa, (struct sigaction *)0);
+
+ setctty(_PATH_CONSOLE);
+
+ argv[0] = "sh";
+ argv[1] = _PATH_RUNDOWN;
+ argv[2] = 0;
+
+ sigprocmask(SIG_SETMASK, &sa.sa_mask, (sigset_t *) 0);
+
+ execv(_PATH_BSHELL, argv);
+ stall("can't exec %s for %s: %m", _PATH_BSHELL, _PATH_RUNDOWN);
+ _exit(1); /* force single user mode */
+ }
+
+ if (pid == -1) {
+ emergency("can't fork for %s on %s: %m",
+ _PATH_BSHELL, _PATH_RUNDOWN);
+ while (waitpid(-1, (int *) 0, WNOHANG) > 0)
+ continue;
+ sleep(STALL_TIMEOUT);
+ return 1;
+ }
+
+ /*
+ * Copied from single_user(). This is a bit paranoid.
+ */
+ do {
+ if ((wpid = waitpid(-1, &status, WUNTRACED)) != -1)
+ collect_child(wpid);
+ if (wpid == -1) {
+ if (errno == EINTR)
+ continue;
+ warning("wait for %s on %s failed: %m; going to single user mode",
+ _PATH_BSHELL, _PATH_RUNDOWN);
+ return 2;
+ }
+ if (wpid == pid && WIFSTOPPED(status)) {
+ warning("init: %s on %s stopped, restarting\n",
+ _PATH_BSHELL, _PATH_RUNDOWN);
+ kill(pid, SIGCONT);
+ wpid = -1;
+ }
+ } while (wpid != pid);
+
+ if (WIFSIGNALED(status) && WTERMSIG(status) == SIGTERM &&
+ requested_transition == catatonia) {
+ /* /etc/rc executed /sbin/reboot; wait for the end quietly */
+ sigset_t s;
+
+ sigfillset(&s);
+ for (;;)
+ sigsuspend(&s);
+ }
+
+ if (!WIFEXITED(status)) {
+ warning("%s on %s terminated abnormally, going to single user mode",
+ _PATH_BSHELL, _PATH_RUNDOWN);
+ return 1;
+ }
+
+ if (WEXITSTATUS(status))
+ return 2;
}
===================================================================
RCS file: /build/master/freebsd/init/pathnames.h,v
retrieving revision 1.1.1.1
diff -u -r1.1.1.1 pathnames.h
--- 1.1.1.1 1994/05/26 06:34:19
+++ pathnames.h 1994/12/22 13:37:45
@@ -40,3 +40,4 @@
#define _PATH_SLOGGER "/sbin/session_logger"
#define _PATH_RUNCOM "/etc/rc"
+#define _PATH_RUNDOWN "/etc/rc.shutdown"
--
Ollivier ROBERT -=- FreeBSD: the daemon is FREE! -=- roberto@freebsd.org
FreeBSD keltia 2.1.0-Development #0: Sun Dec 11 20:52:22 1994
roberto@keltia:/usr/src/sys/compile/KELTIA i386 ctm#221
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?9412221415.AA02591>
