[patch] halt/reboot/shutdown cleanup
Warner Losh
imp at bsdimp.com
Mon May 14 01:24:42 UTC 2012
After the short discussion on IRC, I don't think that there's consensus this patch is a good idea at all. I don't recall that being the outcome of the last round of discussions either.
Maybe we need:
#!/bin/sh
case ${HALT_METHOD:-bsd} in
*) /sbin/bsdhalt $*
linux) /sbin/shutdown -h $* now
esac
and similar for reboot, since that would also solve the problem...
Warner
On May 13, 2012, at 4:06 PM, Jilles Tjoelker wrote:
> There is duplication of code between sbin/reboot and init: both can
> cleanly shut down the system, for some value of "cleanly". Because the
> code in init is activated by the kernel (sending a signal to init), it
> makes sense to keep that and remove the duplicate from sbin/reboot. This
> also ensures that /etc/rc.shutdown is executed in all "clean" shutdowns.
>
> Before 9.0, init could not shut down the system 100% correctly during
> single user mode (for example, it inappropriately ran /etc/rc.shutdown),
> but this has been fixed.
>
> Also, the normal forms of halt and reboot will now call shutdown so
> users get a clear message of the event.
>
> Halt and reboot still support the -q option to invoke reboot(2) without
> anything else. The -d and -n options now require -q (because init is
> signaled if -q is not used, and init will not do dump or nosync).
>
> The -l option of halt and reboot now not only suppresses logging, but
> also user notification. It does this by signaling init directly and not
> going through shutdown.
>
> The -o option of shutdown goes away because there does not seem any
> point in executing halt or reboot if they are going to send the same
> signal to init anyway.
>
> diff --git a/include/paths.h b/include/paths.h
> index 6503934..f93cf39 100644
> --- a/include/paths.h
> +++ b/include/paths.h
> @@ -84,6 +84,7 @@
> #define _PATH_RSH "/usr/bin/rsh"
> #define _PATH_SENDMAIL "/usr/sbin/sendmail"
> #define _PATH_SHELLS "/etc/shells"
> +#define _PATH_SHUTDOWN "/sbin/shutdown"
> #define _PATH_TTY "/dev/tty"
> #define _PATH_UNIX "don't use _PATH_UNIX"
> #define _PATH_VI "/usr/bin/vi"
> diff --git a/sbin/reboot/reboot.8 b/sbin/reboot/reboot.8
> index 13d7098..50c27ee 100644
> --- a/sbin/reboot/reboot.8
> +++ b/sbin/reboot/reboot.8
> @@ -55,12 +55,11 @@ The
> .Nm halt
> and
> .Nm
> -utilities flush the file system cache to disk, send all running processes
> -a
> -.Dv SIGTERM
> -(and subsequently a
> -.Dv SIGKILL )
> -and, respectively, halt or restart the system.
> +utilities invoke
> +.Xr shutdown 8
> +or signal
> +.Xr init 8
> +to, respectively, halt or restart the system.
> The action is logged, including entering a shutdown record into the user
> accounting database.
> .Pp
> @@ -69,7 +68,9 @@ The options are as follows:
> .It Fl d
> The system is requested to create a crash dump.
> This option is
> -supported only when rebooting, and it has no effect unless a dump
> +supported only when rebooting together with the
> +.Fl q
> +option, and it has no effect unless a dump
> device has previously been specified with
> .Xr dumpon 8 .
> .It Fl k Ar kernel
> @@ -86,25 +87,14 @@ This may change in the future.
> .It Fl l
> The halt or reboot is
> .Em not
> -logged to the system log.
> -This option is intended for applications such as
> -.Xr shutdown 8 ,
> -that call
> -.Nm
> -or
> -.Nm halt
> -and log this themselves.
> +logged to the system log and not announced to users.
> .It Fl n
> The file system cache is not flushed.
> -This option should probably not be used.
> +This option should probably not be used and only works together with the
> +.Fl q
> +option.
> .It Fl p
> The system will turn off the power if it can.
> -If the power down action fails, the system
> -will halt or reboot normally, depending on whether
> -.Nm halt
> -or
> -.Nm
> -was called.
> .It Fl q
> The system is halted or restarted quickly and ungracefully, and only
> the flushing of the file system cache is performed (if the
> @@ -122,12 +112,6 @@ utilities are nothing more than aliases for the
> and
> .Nm
> utilities.
> -.Pp
> -Normally, the
> -.Xr shutdown 8
> -utility is used when the system needs to be halted or restarted, giving
> -users advance warning of their impending doom and cleanly terminating
> -specific programs.
> .Sh SEE ALSO
> .Xr getutxent 3 ,
> .Xr boot 8 ,
> diff --git a/sbin/reboot/reboot.c b/sbin/reboot/reboot.c
> index d927db0..285437a 100644
> --- a/sbin/reboot/reboot.c
> +++ b/sbin/reboot/reboot.c
> @@ -44,31 +44,27 @@ __FBSDID("$FreeBSD$");
> #include <sys/reboot.h>
> #include <sys/time.h>
> #include <sys/types.h>
> -#include <sys/sysctl.h>
> #include <signal.h>
> #include <err.h>
> #include <errno.h>
> #include <fcntl.h>
> +#include <paths.h>
> #include <pwd.h>
> #include <syslog.h>
> #include <stdio.h>
> #include <stdlib.h>
> #include <string.h>
> #include <unistd.h>
> -#include <utmpx.h>
>
> static void usage(void);
> -static u_int get_pageins(void);
>
> static int dohalt;
>
> int
> main(int argc, char *argv[])
> {
> - struct utmpx utx;
> const struct passwd *pw;
> - int ch, howto, i, fd, lflag, nflag, qflag, sverrno;
> - u_int pageins;
> + int ch, howto, fd, lflag, qflag;
> const char *user, *kernel = NULL;
>
> if (strcmp(getprogname(), "halt") == 0) {
> @@ -76,7 +72,7 @@ main(int argc, char *argv[])
> howto = RB_HALT;
> } else
> howto = 0;
> - lflag = nflag = qflag = 0;
> + lflag = qflag = 0;
> while ((ch = getopt(argc, argv, "dk:lnpq")) != -1)
> switch(ch) {
> case 'd':
> @@ -89,7 +85,6 @@ main(int argc, char *argv[])
> lflag = 1;
> break;
> case 'n':
> - nflag = 1;
> howto |= RB_NOSYNC;
> break;
> case 'p':
> @@ -107,6 +102,10 @@ main(int argc, char *argv[])
>
> if ((howto & (RB_DUMP | RB_HALT)) == (RB_DUMP | RB_HALT))
> errx(1, "cannot dump (-d) when halting; must reboot instead");
> + if (!qflag && (howto & RB_DUMP) != 0)
> + errx(1, "cannot dump (-d) without immediate reboot(2) (-q)");
> + if (!qflag && (howto & RB_NOSYNC) != 0)
> + errx(1, "cannot disable sync (-n) without immediate reboot(2) (-q)");
> if (geteuid()) {
> errno = EPERM;
> err(1, NULL);
> @@ -129,6 +128,16 @@ main(int argc, char *argv[])
> }
> }
>
> +#ifndef RESCUE
> + if (!lflag) {
> + execl(_PATH_SHUTDOWN, _PATH_SHUTDOWN,
> + (howto & RB_POWEROFF) != 0 ? "-p" :
> + (howto & RB_HALT) != 0 ? "-h" :
> + "-r", "now", (char *)NULL);
> + warn("cannot execute %s; signaling init(8)", _PATH_SHUTDOWN);
> + }
> +#endif
> +
> /* Log the reboot. */
> if (!lflag) {
> if ((user = getlogin()) == NULL)
> @@ -142,80 +151,12 @@ main(int argc, char *argv[])
> syslog(LOG_CRIT, "rebooted by %s", user);
> }
> }
> - utx.ut_type = SHUTDOWN_TIME;
> - gettimeofday(&utx.ut_tv, NULL);
> - pututxline(&utx);
> -
> - /*
> - * Do a sync early on, so disks start transfers while we're off
> - * killing processes. Don't worry about writes done before the
> - * processes die, the reboot system call syncs the disks.
> - */
> - if (!nflag)
> - sync();
> -
> - /*
> - * Ignore signals that we can get as a result of killing
> - * parents, group leaders, etc.
> - */
> - (void)signal(SIGHUP, SIG_IGN);
> - (void)signal(SIGINT, SIG_IGN);
> - (void)signal(SIGQUIT, SIG_IGN);
> - (void)signal(SIGTERM, SIG_IGN);
> - (void)signal(SIGTSTP, SIG_IGN);
> -
> - /*
> - * If we're running in a pipeline, we don't want to die
> - * after killing whatever we're writing to.
> - */
> - (void)signal(SIGPIPE, SIG_IGN);
> -
> - /* Just stop init -- if we fail, we'll restart it. */
> - if (kill(1, SIGTSTP) == -1)
> - err(1, "SIGTSTP init");
> -
> - /* Send a SIGTERM first, a chance to save the buffers. */
> - if (kill(-1, SIGTERM) == -1 && errno != ESRCH)
> - err(1, "SIGTERM processes");
> -
> - /*
> - * After the processes receive the signal, start the rest of the
> - * buffers on their way. Wait 5 seconds between the SIGTERM and
> - * the SIGKILL to give everybody a chance. If there is a lot of
> - * paging activity then wait longer, up to a maximum of approx
> - * 60 seconds.
> - */
> - sleep(2);
> - for (i = 0; i < 20; i++) {
> - pageins = get_pageins();
> - if (!nflag)
> - sync();
> - sleep(3);
> - if (get_pageins() == pageins)
> - break;
> - }
> -
> - for (i = 1;; ++i) {
> - if (kill(-1, SIGKILL) == -1) {
> - if (errno == ESRCH)
> - break;
> - goto restart;
> - }
> - if (i > 5) {
> - (void)fprintf(stderr,
> - "WARNING: some process(es) wouldn't die\n");
> - break;
> - }
> - (void)sleep(2 * i);
> - }
> -
> - reboot(howto);
> - /* FALLTHROUGH */
>
> -restart:
> - sverrno = errno;
> - errx(1, "%s%s", kill(1, SIGHUP) == -1 ? "(can't restart init): " : "",
> - strerror(sverrno));
> + if (kill(1, (howto & RB_POWEROFF) != 0 ? SIGUSR2 :
> + (howto & RB_HALT) != 0 ? SIGUSR1 :
> + SIGINT) == -1)
> + err(1, "signal init");
> + pause();
> /* NOTREACHED */
> }
>
> @@ -228,18 +169,3 @@ usage(void)
> "usage: reboot [-dlnpq] [-k kernel]\n");
> exit(1);
> }
> -
> -static u_int
> -get_pageins(void)
> -{
> - u_int pageins;
> - size_t len;
> -
> - len = sizeof(pageins);
> - if (sysctlbyname("vm.stats.vm.v_swappgsin", &pageins, &len, NULL, 0)
> - != 0) {
> - warnx("v_swappgsin");
> - return (0);
> - }
> - return pageins;
> -}
> diff --git a/sbin/shutdown/shutdown.8 b/sbin/shutdown/shutdown.8
> index b7067e1..37152ac 100644
> --- a/sbin/shutdown/shutdown.8
> +++ b/sbin/shutdown/shutdown.8
> @@ -42,10 +42,6 @@
> .Fl h | Fl p |
> .Fl r | Fl k
> .Oc
> -.Oo
> -.Fl o
> -.Op Fl n
> -.Oc
> .Ar time
> .Op Ar warning-message ...
> .Nm poweroff
> @@ -77,30 +73,6 @@ The
> option
> does not actually halt the system, but leaves the
> system multi-user with logins disabled (for all but super-user).
> -.It Fl o
> -If one of the
> -.Fl h ,
> -.Fl p
> -or
> -.Fl r
> -options are specified,
> -.Nm
> -will execute
> -.Xr halt 8
> -or
> -.Xr reboot 8
> -instead of sending a signal to
> -.Xr init 8 .
> -.It Fl n
> -If the
> -.Fl o
> -option is specified, prevent the file system cache from being flushed by passing
> -.Fl n
> -to
> -.Xr halt 8
> -or
> -.Xr reboot 8 .
> -This option should probably not be used.
> .It Ar time
> .Ar Time
> is the time at which
> diff --git a/sbin/shutdown/shutdown.c b/sbin/shutdown/shutdown.c
> index 6e662a8..945bef2 100644
> --- a/sbin/shutdown/shutdown.c
> +++ b/sbin/shutdown/shutdown.c
> @@ -88,9 +88,9 @@ static struct interval {
> #undef S
>
> static time_t offset, shuttime;
> -static int dohalt, dopower, doreboot, killflg, mbuflen, oflag;
> +static int dohalt, dopower, doreboot, killflg, mbuflen;
> static char mbuf[BUFSIZ];
> -static const char *nosync, *whom;
> +static const char *whom;
>
> static void badtime(void);
> static void perform_shutdown(void);
> @@ -116,7 +116,6 @@ main(int argc, char **argv)
> errx(1, "NOT super-user");
> #endif
>
> - nosync = NULL;
> readstdin = 0;
>
> /*
> @@ -152,10 +151,8 @@ main(int argc, char **argv)
> killflg = 1;
> break;
> case 'n':
> - nosync = "-n";
> - break;
> case 'o':
> - oflag = 1;
> + /* Ignore -n and -o for compatibility. */
> break;
> case 'p':
> dopower = 1;
> @@ -176,12 +173,6 @@ main(int argc, char **argv)
> if (killflg + doreboot + dohalt + dopower > 1)
> usage("incompatible switches -h, -k, -p and -r");
>
> - if (oflag && !(dohalt || dopower || doreboot))
> - usage("-o requires -h, -p or -r");
> -
> - if (nosync != NULL && !oflag)
> - usage("-n requires -o");
> -
> getoffset(*argv++);
>
> poweroff:
> @@ -351,8 +342,6 @@ timeout(int signo __unused)
> static void
> perform_shutdown(void)
> {
> - char *empty_environ[] = { NULL };
> -
> syslog(LOG_NOTICE, "%s by %s: %s",
> doreboot ? "reboot" : dohalt ? "halt" : dopower ? "power-down" :
> "shutdown", whom, mbuf);
> @@ -370,39 +359,12 @@ perform_shutdown(void)
> (void)printf("halt");
> else if (dopower)
> (void)printf("power-down");
> - if (nosync != NULL)
> - (void)printf(" no sync");
> (void)printf("\nkill -HUP 1\n");
> #else
> - if (!oflag) {
> - (void)kill(1, doreboot ? SIGINT : /* reboot */
> - dohalt ? SIGUSR1 : /* halt */
> - dopower ? SIGUSR2 : /* power-down */
> - SIGTERM); /* single-user */
> - } else {
> - if (doreboot) {
> - execle(_PATH_REBOOT, "reboot", "-l", nosync,
> - (char *)NULL, empty_environ);
> - syslog(LOG_ERR, "shutdown: can't exec %s: %m.",
> - _PATH_REBOOT);
> - warn(_PATH_REBOOT);
> - }
> - else if (dohalt) {
> - execle(_PATH_HALT, "halt", "-l", nosync,
> - (char *)NULL, empty_environ);
> - syslog(LOG_ERR, "shutdown: can't exec %s: %m.",
> - _PATH_HALT);
> - warn(_PATH_HALT);
> - }
> - else if (dopower) {
> - execle(_PATH_HALT, "halt", "-l", "-p", nosync,
> - (char *)NULL, empty_environ);
> - syslog(LOG_ERR, "shutdown: can't exec %s: %m.",
> - _PATH_HALT);
> - warn(_PATH_HALT);
> - }
> - (void)kill(1, SIGTERM); /* to single-user */
> - }
> + (void)kill(1, doreboot ? SIGINT : /* reboot */
> + dohalt ? SIGUSR1 : /* halt */
> + dopower ? SIGUSR2 : /* power-down */
> + SIGTERM); /* single-user */
> #endif
> finish(0);
> }
> @@ -534,7 +496,7 @@ usage(const char *cp)
> if (cp != NULL)
> warnx("%s", cp);
> (void)fprintf(stderr,
> - "usage: shutdown [-] [-h | -p | -r | -k] [-o [-n]] time [warning-message ...]\n"
> + "usage: shutdown [-] [-h | -p | -r | -k] time [warning-message ...]\n"
> " poweroff\n");
> exit(1);
> }
>
> --
> Jilles Tjoelker
> _______________________________________________
> freebsd-arch at freebsd.org mailing list
> http://lists.freebsd.org/mailman/listinfo/freebsd-arch
> To unsubscribe, send any mail to "freebsd-arch-unsubscribe at freebsd.org"
>
>
More information about the freebsd-arch
mailing list