Date: Mon, 7 Jul 1997 22:51:49 +0200 From: Ollivier Robert <roberto@keltia.freenix.fr> To: hackers@FreeBSD.ORG Subject: /etc/rc.shutdown (Was: Re: DEVFS permissions &c.) Message-ID: <19970707225149.19828@keltia.freenix.fr> In-Reply-To: <Mutt.19970112183542.j@uriah.heep.sax.de>; from J Wunsch on Sun, Jan 12, 1997 at 06:35:42PM %2B0100 References: <Mutt.19970111201007.j@uriah.heep.sax.de> <16902.853042470@time.cdrom.com> <Mutt.19970112112012.j@uriah.heep.sax.de> <Mutt.19970112160314.roberto@keltia.freenix.fr> <Mutt.19970112183542.j@uriah.heep.sax.de>
next in thread | previous in thread | raw e-mail | index | archive | help
[ digging this old mail from my archive, I love Glimpse ] According to J Wunsch (a long time ago): > I think stall() is the wrong thing to do here. If the shutdown script > fails, it's best to log what can be logged, and proceed to really shut > down the system to the desired state. stall() is the same function as warning() except that it waits for STALL_TIMEOUT (browsing through init.c again, there are a fes places where warning() is used and then a sleep() is done just after...). Both are syslogging. So even with stall, it will proceed if runshutdown() returns. In this case, stall is better IMO because if you're at the console you'll have time to see the message... If not, you won't be too disturbed (except by waiting a bit more of course). > Here's an alarm() missing, to prevent infinite hangs of the shutdown > script. Such an infinite hang should be answered with sending > rc.shutdown a terminate signal, and by syslogging it. Will do. What do you people think of this (against current of course) ? My ALRM handling may be a bit off track so I welcome comments (and diffs :-)). Index: init.8 =================================================================== RCS file: /spare/FreeBSD-current/src/sbin/init/init.8,v retrieving revision 1.9 diff -u -2 -r1.9 init.8 --- init.8 1997/04/01 20:41:04 1.9 +++ init.8 1997/07/07 20:19:36 @@ -242,4 +242,13 @@ or from X when the machine 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 @@ -281,4 +290,6 @@ .It Pa /etc/rc System startup commands. +.It Pa /etc/rc.shutdown +System shutdown commands. .El .Sh SEE ALSO Index: init.c =================================================================== RCS file: /spare/FreeBSD-current/src/sbin/init/init.c,v retrieving revision 1.17 diff -u -2 -r1.17 init.c --- init.c 1997/06/13 06:24:42 1.17 +++ init.c 1997/07/07 20:49:39 @@ -98,4 +98,5 @@ #define STALL_TIMEOUT 30 /* wait N secs after warning */ #define DEATH_WATCH 10 /* wait N secs for procs to die */ +#define DEATH_SCRIPT 120 /* wait for 2mn for /etc/rc.shutdown */ #define RESOURCE_RC "daemon" #define RESOURCE_WINDOW "default" @@ -110,4 +111,5 @@ void disaster __P((int)); void badsys __P((int)); +int runshutdown __P((void)); /* @@ -1385,4 +1387,5 @@ { register session_t *sp; + register int rcdown; register int i; pid_t pid; @@ -1392,4 +1395,10 @@ sp->se_flags |= SE_SHUTDOWN; + /* Try to run the rc.shutdown script within a period of time */ + rcdown = runshutdown(); + if (rcdown) + stall("Could not run %s, proceeding with shutdown anyway.", + _PATH_RUNDOWN); + /* NB: should send a message to the session logger to avoid blocking. */ logwtmp("~", "shutdown", ""); @@ -1413,4 +1422,99 @@ 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. + * Use the same ALRM handler. + */ + alarm(DEATH_SCRIPT); + do { + if ((wpid = waitpid(-1, &status, WUNTRACED)) != -1) + collect_child(wpid); + if (wpid == -1 || clang == 1) { + if (errno == EINTR) + continue; + if (clang) { + /* we were waiting for the sub-shell */ + kill(wpid, SIGTERM); + warning("timeout expired for %s on %s: %m; goinh to single used mode", + _PATH_BSHELL, _PATH_RUNDOWN); + } + else + 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 && !clang); + + 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; } char * Index: pathnames.h =================================================================== RCS file: /spare/FreeBSD-current/src/sbin/init/pathnames.h,v retrieving revision 1.1.1.1 diff -u -2 -r1.1.1.1 pathnames.h --- pathnames.h 1994/05/26 06:34:19 1.1.1.1 +++ pathnames.h 1997/07/07 20:19:36 @@ -41,2 +41,3 @@ #define _PATH_SLOGGER "/sbin/session_logger" #define _PATH_RUNCOM "/etc/rc" +#define _PATH_RUNDOWN "/etc/rc.shutdown" -- Ollivier ROBERT -=- FreeBSD: There are no limits -=- roberto@keltia.freenix.fr FreeBSD keltia.freenix.fr 3.0-CURRENT #20: Fri Jun 13 00:16:13 CEST 1997
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?19970707225149.19828>