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>