Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 12 Jan 1997 16:03:14 +0100
From:      roberto@keltia.freenix.fr (Ollivier Robert)
To:        hackers@freebsd.org
Subject:   Re: DEVFS permissions &c.
Message-ID:  <Mutt.19970112160314.roberto@keltia.freenix.fr>
In-Reply-To: <Mutt.19970112112012.j@uriah.heep.sax.de>; from J Wunsch on Jan 12, 1997 11:20:12 %2B0100
References:  <Mutt.19970111201007.j@uriah.heep.sax.de> <16902.853042470@time.cdrom.com> <Mutt.19970112112012.j@uriah.heep.sax.de>

next in thread | previous in thread | raw e-mail | index | archive | help
According to J Wunsch:
> the current ideas of a SysV init? :-) Well, at least we could teach
> our init to run something like /etc/rc.shutdown or such, which can do
> all the dirty work.  Init should probably impose a timeout for this
> script (in case it hangs), how to configure this?  A sysctl variable?
> For normal machines (i.e., not news servers or other machines that
> require mucho work at shutdown time), a grace period of 10 seconds
> should suffice.

May I remind everyone that I proposed a change for this in 1994 ? :-)

Here is the patch again, against pre-2.0 init of course so it must be
modified now. It was at the time a partial patch because the discussions at
that time pushed for changing reboot/halt as well.

I have this under CVS so I could probably merge it with our current init.

In this scheme, init does all the job of bringing the system down and
reboot/halt only send a signal to init instead of doing the job themselves.
The patch for reboot/halt has to be written though.

Now that you can have rc.d directory upon statup, we could teach
rc.shutdown to use the rc.d/ scheme as well in order to have proper
init/shutdown time initializations...

All my rc.d scripts already supports "start" and "stop" arguments for
example...

----------------------------------------------------
#! /bin/sh
PATH=$PATH:/usr/local/news/etc:/usr/local/news/bin
export PATH

if [ X"$1" = Xstart ]; then
	echo ''
	su news -c rc.news
fi

if [ X"$1" = Xstop ]; then
	echo 'Stopping INN.'
	su news -c "ctlinnd shutdown 'Halted by news.sh stop'"
fi
----------------------------------------------------

===================================================================
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    -=- The daemon is FREE! -=-    roberto@keltia.freenix.fr
  FreeBSD keltia.freenix.fr 3.0-CURRENT #33: Sat Dec 21 12:57:17 CET 1996



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?Mutt.19970112160314.roberto>