From owner-freebsd-hackers Thu Dec 22 06:14:41 1994 Return-Path: hackers-owner Received: (from root@localhost) by freefall.cdrom.com (8.6.9/8.6.6) id GAA02412 for hackers-outgoing; Thu, 22 Dec 1994 06:14:41 -0800 Received: from ibp.ibp.fr (ibp.ibp.fr [132.227.60.30]) by freefall.cdrom.com (8.6.9/8.6.6) with ESMTP id OAA02406 for ; Thu, 22 Dec 1994 14:14:38 GMT Received: from blaise.ibp.fr (blaise.ibp.fr [132.227.60.1]) by ibp.ibp.fr (8.6.8/jtpda-5.0) with SMTP id PAA09921 for ; Thu, 22 Dec 1994 15:14:49 +0100 Received: by blaise.ibp.fr (4.1/SMI-4.1) id AA02591; Thu, 22 Dec 94 15:15:11 +0100 From: roberto@blaise.ibp.fr (Ollivier ROBERT) Message-Id: <9412221415.AA02591@blaise.ibp.fr> Subject: /etc/rc.shutdown (First shot) To: hackers@freebsd.org (Hackers' list FreeBSD) Date: Thu, 22 Dec 1994 15:15:11 +0100 (MET) X-Mailer: ELM [version 2.4 PL23beta2] Mime-Version: 1.0 Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: 8bit Content-Length: 4757 Sender: hackers-owner@freebsd.org Precedence: bulk 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