The branch main has been updated by des: URL: https://cgit.FreeBSD.org/src/commit/?id=4453ec5b8716bc465ff5192986099dc75d1f2ce7
commit 4453ec5b8716bc465ff5192986099dc75d1f2ce7 Author: Dag-Erling Smørgrav <[email protected]> AuthorDate: 2025-12-10 14:45:57 +0000 Commit: Dag-Erling Smørgrav <[email protected]> CommitDate: 2025-12-10 14:45:57 +0000 reboot: Default to a clean shutdown * If invoked as fasthalt or fastboot, behavior is unchanged. * If not invoked as fasthalt or fastboot, we simply signal init(8), just like shutdown(8) does, instead of taking the system down ourselves. * Since only init can handle the RB_REROOT case, the -r flag is not supported in fast mode. * Update the usage string to correctly reflect the program being run (fast or normal; halt, boot, or nextboot) and the options available in each case. * Update the manual page to make the distinction between normal and fast mode clear, better explain what shutdown(8) still does that reboot(8) does not, and add a historical note explaining what the difference between the two used to be. MFC after: 1 month Relnotes: yes Reviewed by: imp Differential Revision: https://reviews.freebsd.org/D54117 --- sbin/reboot/reboot.8 | 62 ++++++++++++++++++++++++++++++++++++++-------------- sbin/reboot/reboot.c | 58 ++++++++++++++++++++++++++++++++++-------------- 2 files changed, 88 insertions(+), 32 deletions(-) diff --git a/sbin/reboot/reboot.8 b/sbin/reboot/reboot.8 index 1bbc39d52be4..4d35336efefb 100644 --- a/sbin/reboot/reboot.8 +++ b/sbin/reboot/reboot.8 @@ -25,7 +25,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.Dd April 12, 2025 +.Dd December 8, 2025 .Dt REBOOT 8 .Os .Sh NAME @@ -60,16 +60,25 @@ The .Nm halt and .Nm -utilities flush the file system cache to disk, send all running processes -a +utilities stop and restart the system, respectively. +.Pp +Both utilities have two distinct modes of operation. +In normal mode, they send a signal to the +.Xr init 8 +process, which shuts down running services and stops or restarts the +system. +In fast mode, they 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. -The action is logged, including entering a shutdown record into the user -accounting database. +and stop or restart the system themselves. +Services are killed, not shut down, which may result in data loss. .Pp -The options are as follows: +In either mode, the action is logged, including entering a shutdown +record into the user accounting database. +.Pp +The following options are available: .Bl -tag -width indent .It Fl c The system will turn off the power and then turn it back on if it can. @@ -111,14 +120,17 @@ Care should be taken if contains any characters that are special to the shell or loader's configuration parsing code. .It Fl f -Force reboot. +Forced mode. Normally, +.Nm halt +or .Nm checks for the presence of the next kernel, and absence of the .Pa /var/run/noshutdown file. -Without this flag, reboot is denied if one of the conditions failed. +Without this flag, the operation is rejected if one of these checks +fails. .It Fl k Ar kname Boot the specified kernel .Ar kname @@ -195,17 +207,20 @@ The .Nm fasthalt and .Nm fastboot -utilities are nothing more than aliases for the +utilities invoke .Nm halt and -.Nm -utilities. +.Nm , +respectively, in fast mode. .Pp -Normally, the +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. +utility can be used to not only stop or restart the system right away, +but also schedule a stop or restart in the future, and will, unlike +.Nm halt +and +.Nm , +give users advance warning of their impending doom. .Sh EXAMPLES Replace current root filesystem with UFS mounted from .Pa /dev/ada0s1a : @@ -236,3 +251,18 @@ A .Nm utility appeared in .Bx 4.0 . +.Pp +Historically, the +.Xr shutdown 8 +utility was used when the system needed to be halted or restarted +cleanly in the normal course of operations, and the +.Nm halt +and +.Nm +utilities were blunt instruments used only in single-user mode or if +exceptional circumstances made a normal shutdown impractical. +As other operating systems did away with this distinction, and it +became clear that many users were unaware of it and were using +.Nm +in the belief that it performed a clean shutdown, it was rewritten to +conform to that expectation. diff --git a/sbin/reboot/reboot.c b/sbin/reboot/reboot.c index 59ae83ef6f6a..a147b7e08a95 100644 --- a/sbin/reboot/reboot.c +++ b/sbin/reboot/reboot.c @@ -59,6 +59,7 @@ extern char **environ; static void usage(void) __dead2; static uint64_t get_pageins(void); +static bool dofast; static bool dohalt; static bool donextboot; @@ -229,6 +230,24 @@ add_env(char **env, const char *key, const char *value) free(oldenv); } +static void +shutdown(int howto) +{ + char sigstr[SIG2STR_MAX]; + int signo = + howto & RB_HALT ? SIGUSR1 : + howto & RB_POWEROFF ? SIGUSR2 : + howto & RB_POWERCYCLE ? SIGWINCH : + howto & RB_REROOT ? SIGEMT : + SIGINT; + + (void)sig2str(signo, sigstr); + BOOTTRACE("SIG%s to init(8)...", sigstr); + if (kill(1, signo) == -1) + err(1, "SIG%s init", sigstr); + exit(0); +} + /* * Different options are valid for different programs. */ @@ -239,18 +258,24 @@ int main(int argc, char *argv[]) { struct utmpx utx; - const struct passwd *pw; struct stat st; + const struct passwd *pw; + const char *progname, *user; + const char *kernel = NULL, *getopts = GETOPT_REBOOT; + char *env = NULL, *v; + uint64_t pageins; int ch, howto = 0, i, sverrno; bool aflag, Dflag, fflag, lflag, Nflag, nflag, qflag; - uint64_t pageins; - const char *user, *kernel = NULL, *getopts = GETOPT_REBOOT; - char *env = NULL, *v; - if (strstr(getprogname(), "halt") != NULL) { + progname = getprogname(); + if (strncmp(progname, "fast", 4) == 0) { + dofast = true; + progname += 4; + } + if (strcmp(progname, "halt") == 0) { dohalt = true; howto = RB_HALT; - } else if (strcmp(getprogname(), "nextboot") == 0) { + } else if (strcmp(progname, "nextboot") == 0) { donextboot = true; getopts = GETOPT_NEXTBOOT; /* Note: reboot's extra opts return '?' */ } else { @@ -331,6 +356,8 @@ main(int argc, char *argv[]) errx(1, "-c and -p cannot be used together"); if ((howto & RB_REROOT) != 0 && howto != RB_REROOT) errx(1, "-r cannot be used with -c, -d, -n, or -p"); + if ((howto & RB_REROOT) != 0 && dofast) + errx(1, "-r cannot be performed in fast mode"); if ((howto & RB_REROOT) != 0 && kernel != NULL) errx(1, "-r and -k cannot be used together, there is no next kernel"); @@ -438,14 +465,10 @@ main(int argc, char *argv[]) (void)signal(SIGPIPE, SIG_IGN); /* - * Only init(8) can perform rerooting. + * Common case: clean shutdown. */ - if (howto & RB_REROOT) { - if (kill(1, SIGEMT) == -1) - err(1, "SIGEMT init"); - - return (0); - } + if (!dofast) + shutdown(howto); /* Just stop init -- if we fail, we'll restart it. */ BOOTTRACE("SIGTSTP to init(8)..."); @@ -507,9 +530,12 @@ usage(void) fprintf(stderr, "usage: nextboot [-aDf] " "[-e name=value] [-k kernel] [-o options]\n"); } else { - fprintf(stderr, dohalt ? - "usage: halt [-clNnpq] [-k kernel]\n" : - "usage: reboot [-cdlNnpqr] [-k kernel]\n"); + fprintf(stderr, "usage: %s%s [-%sflNnpq%s] " + "[-e name=value] [-k kernel] [-o options]\n", + dofast ? "fast" : "", + dohalt ? "halt" : dofast ? "boot" : "reboot", + dohalt ? "D" : "cDd", + dohalt || dofast ? "" : "r"); } exit(1); }
