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>