dplatt@coherent.com (Dave Platt) (10/11/88)
I've made some modifications to the Aufs file-server software in the CAP
5.0 distribution. With these changes in place, Aufs will "notice" that
the superuser has issued a "shutdown" command; Aufs will notify its
clients of the impending shutdown and ask that they log off. It is no
longer necessary to manually send a "kill" signal to the Aufs daemon in
order to trigger the shutdown sequence.
Mechanism: The main Aufs daemon now checks roughly once per minute for
the appearance of the "/etc/nologin" file. This file is written by the
"/etc/shutdown" program five minutes before the system is actually shut
down. When the Aufs daemon sees that this file has appeared, it sends a
"terminate" signal to all session subprocesses (just as if it had
received a "kill" signal from the superuser).
When the user-session subprocesses receive a "terminate" signal, they
check to see whether the /etc/nologin file exists. If it does, they
enter an accelerated 3-minute shutdown cycle, rather than the usual
5-minute cycle. This ensures that the subprocesses will have had time
to complete the 3-minute cycle and exit cleanly before the 5-minute
/etc/shutdown sequence is completed.
I've made one additional change to the shutdown code. When the main
server process decides to shut down (either due to a "kill" signal or
due to the appearance of the /etc/nologin file), it _immediately_ calls
SrvrShutdown() to remove itself from the host's name-binding tables. In
the release version of CAP 5.0, Aufs would not remove itself from the
NBP tables until it was ready to exit; new users could connect to the
server during the 5-minute shutdown cycle and be abruptly cut off
without warning.
These modifications were written for a SunOS 3.5 system, but should work
OK on other BSD variants. Use 'em at your own risk; your mileage may
vary.
*** aufs.c.dist Wed Oct 5 13:51:58 1988
--- aufs.c Wed Oct 5 15:37:43 1988
***************
*** 61,66 ****
--- 61,70 ----
# define NOSHUTDOWNCODE
#endif
+ #ifndef NOSHUTDOWNCODE
+ # include <sys/stat.h>
+ #endif
+
/* known attention codes */
#define AFPSHUTDOWNTIME(x) (0x8000|((x)&0xfff))
#define AFPSHUTDOWNCANCEL (0x8fff)
***************
*** 91,96 ****
--- 95,103 ----
private int cno = -1; /* current connection */
#ifndef NOSHUTDOWNCODE
private int minutes_to_shutdown = -1;
+ private struct stat nologin_status;
+ private int nologin_probe_cycle = 0;
+ private int nbp_shutdown_performed = 0;
#endif
/* if wait3 and usetimes isn't set, then we handle rusage from wait3 */
***************
*** 481,486 ****
--- 488,504 ----
log("Waiting for session %d to activate", cno);
/* won't wait if we set comp above */
while (comp > 0) {
+ #ifndef NOSHUTDOWNCODE
+ if (nologin_probe_cycle++ > 10)
+ {
+ nologin_probe_cycle = 0;
+ if (minutes_to_shutdown < 0 &&
+ stat("/etc/nologin", &nologin_status) == 0)
+ {
+ killin3(); /* start shutdown */
+ }
+ }
+ #endif
abSleep(sectotick(5),TRUE);
gcinferior();
}
***************
*** 558,565 ****
if (statflg)
SrvrPrintStats(); /* print stats */
if (mypid == parent_pid)
! if ((err = SrvrShutdown(&srvr_entity_name)) != noErr)
! log("NBPRemove failed: code %d\n", err);
exit(0);
}
--- 576,586 ----
if (statflg)
SrvrPrintStats(); /* print stats */
if (mypid == parent_pid)
! #ifndef NOSHUTDOWNCODE
! if (!nbp_shutdown_performed)
! #endif
! if ((err = SrvrShutdown(&srvr_entity_name)) != noErr)
! log("NBPRemove failed: code %d\n", err);
exit(0);
}
***************
*** 850,859 ****
{
int dying();
! if (minutes_to_shutdown >= 0) /* already in shutdown mode */
! return;
! log("Superior told us to shutdown by time -- initiating 5 minute shutdown");
! minutes_to_shutdown = 5;
dying(); /* start */
}
--- 877,897 ----
{
int dying();
! if (stat("/etc/nologin", &nologin_status) == 0)
! {
! if (minutes_to_shutdown >= 0 && minutes_to_shutdown <= 3)
! /* already in shutdown mode */
! return;
! log("Noticed /etc/nologin file: initiating 3-minute shutdown");
! minutes_to_shutdown = 3;
! }
! else
! {
! if (minutes_to_shutdown >= 0) /* already in shutdown mode */
! return;
! log("Superior told us to shutdown by time -- initiating 5 minute shutdown");
! minutes_to_shutdown = 5;
! }
dying(); /* start */
}
***************
*** 868,875 ****
signal (SIGHUP, SIG_IGN);
log("Parent received SIGHUP -- immediate shutdown");
killpg (parent_pid, SIGHUP);
! if ((err = SrvrShutdown(&srvr_entity_name)) != noErr)
! log("NBPRemove failed: code %d\n", err);
exit(0);
}
--- 906,914 ----
signal (SIGHUP, SIG_IGN);
log("Parent received SIGHUP -- immediate shutdown");
killpg (parent_pid, SIGHUP);
! if (!nbp_shutdown_performed)
! if ((err = SrvrShutdown(&srvr_entity_name)) != noErr)
! log("NBPRemove failed: code %d\n", err);
exit(0);
}
***************
*** 879,897 ****
--- 918,966 ----
killin5()
{
int killinn();
+ int err;
signal (SIGTERM, SIG_IGN);
log("Shutdown by time -- initiating 5 minute shutdown");
killpg (parent_pid, SIGTERM);
minutes_to_shutdown = 4;
+ if (!nbp_shutdown_performed)
+ {
+ if ((err = SrvrShutdown(&srvr_entity_name)) == noErr)
+ nbp_shutdown_performed = 1;
+ else
+ log("NBPRemove failed: code %d\n", err);
+ }
/* in case children get blocked up */
signal(SIGALRM, killinn);
alarm(68); /* a litte more than a minute */
}
+ killin3()
+ {
+ int killinn();
+ int err;
+
+ signal (SIGTERM, SIG_IGN);
+ log("Shutdown by /etc/nologin -- initiating 3 minute shutdown");
+ killpg (parent_pid, SIGTERM);
+ minutes_to_shutdown = 2;
+ if (!nbp_shutdown_performed)
+ {
+ if ((err = SrvrShutdown(&srvr_entity_name)) == noErr)
+ nbp_shutdown_performed = 1;
+ else
+ log("NBPRemove failed: code %d\n", err);
+ }
+ /* in case children get blocked up */
+ signal(SIGALRM, killinn);
+ alarm(68); /* a litte more than a minute */
+ }
+
killinn()
{
int killinn();
+ int err;
if (minutes_to_shutdown < 0) /* not in die mode */
return;
--
Dave Platt VOICE: (415) 493-8805
USNAIL: Coherent Thought Inc. 3350 West Bayshore #205 Palo Alto CA 94303
UUCP: ...!{ames,sun,uunet}!coherent!dplatt DOMAIN: dplatt@coherent.com
INTERNET: coherent!dplatt@ames.arpa, ...@sun.com, ...@uunet.uu.net