1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright 2010 ProFUSION embedded systems
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
23 #include <sys/types.h>
24 #include <sys/reboot.h>
25 #include <linux/reboot.h>
27 #include <sys/types.h>
29 #include <sys/mount.h>
30 #include <sys/syscall.h>
48 #define TIMEOUT_USEC (5 * USEC_PER_SEC)
49 #define FINALIZE_ATTEMPTS 50
51 static bool ignore_proc(pid_t pid) {
59 /* We are PID 1, let's not commit suicide */
63 r = get_process_uid(pid, &uid);
65 return true; /* not really, but better safe than sorry */
67 /* Non-root processes otherwise are always subject to be killed */
71 snprintf(buf, sizeof(buf), "/proc/%lu/cmdline", (unsigned long) pid);
76 return true; /* not really, but has the desired effect */
78 count = fread(&c, 1, 1, f);
81 /* Kernel threads have an empty cmdline */
85 /* Processes with argv[0][0] = '@' we ignore from the killing
88 * http://www.freedesktop.org/wiki/Software/systemd/RootStorageDaemons */
89 if (count == 1 && c == '@')
95 static int killall(int sign) {
98 unsigned int n_processes = 0;
100 dir = opendir("/proc");
104 while ((d = readdir(dir))) {
107 if (parse_pid(d->d_name, &pid) < 0)
110 if (ignore_proc(pid))
113 if (kill(pid, sign) == 0)
116 log_warning("Could not kill %d: %m", pid);
124 static void wait_for_children(int n_processes, sigset_t *mask) {
129 until = now(CLOCK_MONOTONIC) + TIMEOUT_USEC;
136 pid_t pid = waitpid(-1, NULL, WNOHANG);
141 if (pid < 0 && errno == ECHILD)
145 if (--n_processes == 0)
149 n = now(CLOCK_MONOTONIC);
153 timespec_store(&ts, until - n);
155 if ((k = sigtimedwait(mask, NULL, &ts)) != SIGCHLD) {
157 if (k < 0 && errno != EAGAIN) {
158 log_error("sigtimedwait() failed: %m");
163 log_warning("sigtimedwait() returned unexpected signal.");
168 static void send_signal(int sign) {
169 sigset_t mask, oldmask;
172 assert_se(sigemptyset(&mask) == 0);
173 assert_se(sigaddset(&mask, SIGCHLD) == 0);
174 assert_se(sigprocmask(SIG_BLOCK, &mask, &oldmask) == 0);
176 if (kill(-1, SIGSTOP) < 0 && errno != ESRCH)
177 log_warning("kill(-1, SIGSTOP) failed: %m");
179 n_processes = killall(sign);
181 if (kill(-1, SIGCONT) < 0 && errno != ESRCH)
182 log_warning("kill(-1, SIGCONT) failed: %m");
184 if (n_processes <= 0)
187 wait_for_children(n_processes, &mask);
190 sigprocmask(SIG_SETMASK, &oldmask, NULL);
193 static void ultimate_send_signal(int sign) {
194 sigset_t mask, oldmask;
197 assert_se(sigemptyset(&mask) == 0);
198 assert_se(sigaddset(&mask, SIGCHLD) == 0);
199 assert_se(sigprocmask(SIG_BLOCK, &mask, &oldmask) == 0);
201 if (kill(-1, SIGSTOP) < 0 && errno != ESRCH)
202 log_warning("kill(-1, SIGSTOP) failed: %m");
205 if (r < 0 && errno != ESRCH)
206 log_warning("kill(-1, %s) failed: %m", signal_to_string(sign));
208 if (kill(-1, SIGCONT) < 0 && errno != ESRCH)
209 log_warning("kill(-1, SIGCONT) failed: %m");
214 wait_for_children(0, &mask);
217 sigprocmask(SIG_SETMASK, &oldmask, NULL);
220 static int prepare_new_root(void) {
221 static const char dirs[] =
222 "/run/initramfs/oldroot\0"
223 "/run/initramfs/proc\0"
224 "/run/initramfs/sys\0"
225 "/run/initramfs/dev\0"
226 "/run/initramfs/run\0";
230 if (mount("/run/initramfs", "/run/initramfs", NULL, MS_BIND, NULL) < 0) {
231 log_error("Failed to mount bind /run/initramfs on /run/initramfs: %m");
235 if (mount(NULL, "/run/initramfs", NULL, MS_PRIVATE, NULL) < 0) {
236 log_error("Failed to make /run/initramfs private mount: %m");
240 NULSTR_FOREACH(dir, dirs)
241 if (mkdir_p(dir, 0755) < 0 && errno != EEXIST) {
242 log_error("Failed to mkdir %s: %m", dir);
246 if (mount("/sys", "/run/initramfs/sys", NULL, MS_BIND, NULL) < 0) {
247 log_error("Failed to mount bind /sys on /run/initramfs/sys: %m");
251 if (mount("/proc", "/run/initramfs/proc", NULL, MS_BIND, NULL) < 0) {
252 log_error("Failed to mount bind /proc on /run/initramfs/proc: %m");
256 if (mount("/dev", "/run/initramfs/dev", NULL, MS_BIND, NULL) < 0) {
257 log_error("Failed to mount bind /dev on /run/initramfs/dev: %m");
261 if (mount("/run", "/run/initramfs/run", NULL, MS_BIND, NULL) < 0) {
262 log_error("Failed to mount bind /run on /run/initramfs/run: %m");
269 static int pivot_to_new_root(void) {
272 chdir("/run/initramfs");
275 In case some evil process made "/" MS_SHARED
276 It works for pivot_root, but the ref count for the root device
277 is not decreasing :-/
279 if (mount(NULL, "/", NULL, MS_PRIVATE, NULL) < 0) {
280 log_error("Failed to make \"/\" private mount %m");
284 if (pivot_root(".", "oldroot") < 0) {
285 log_error("pivot failed: %m");
286 /* only chroot if pivot root succeded */
291 log_info("Successfully changed into root pivot.");
293 fd = open("/dev/console", O_RDWR);
295 log_error("Failed to open /dev/console: %m");
299 /* Initialize the controlling terminal */
301 ioctl(STDIN_FILENO, TIOCSCTTY, NULL);
307 int main(int argc, char *argv[]) {
310 bool need_umount = true, need_swapoff = true, need_loop_detach = true, need_dm_detach = true;
311 bool killed_everbody = false, in_container, use_watchdog = false;
313 log_parse_environment();
314 log_set_target(LOG_TARGET_CONSOLE); /* syslog will die if not gone yet */
320 log_error("Not executed by init (pid 1).");
326 log_error("Invalid number of arguments.");
331 in_container = detect_container(NULL) > 0;
333 if (streq(argv[1], "reboot"))
335 else if (streq(argv[1], "poweroff"))
337 else if (streq(argv[1], "halt"))
338 cmd = RB_HALT_SYSTEM;
339 else if (streq(argv[1], "kexec"))
340 cmd = LINUX_REBOOT_CMD_KEXEC;
342 log_error("Unknown action '%s'.", argv[1]);
347 use_watchdog = !!getenv("WATCHDOG_USEC");
349 /* lock us into memory */
350 mlockall(MCL_CURRENT|MCL_FUTURE);
352 log_info("Sending SIGTERM to remaining processes...");
353 send_signal(SIGTERM);
355 log_info("Sending SIGKILL to remaining processes...");
356 send_signal(SIGKILL);
359 need_swapoff = false;
360 need_dm_detach = false;
363 /* Unmount all mountpoints, swaps, and loopback devices */
364 for (retries = 0; retries < FINALIZE_ATTEMPTS; retries++) {
365 bool changed = false;
371 log_info("Unmounting file systems.");
372 r = umount_all(&changed);
376 log_info("Not all file systems unmounted, %d left.", r);
378 log_error("Failed to unmount file systems: %s", strerror(-r));
382 log_info("Disabling swaps.");
383 r = swapoff_all(&changed);
385 need_swapoff = false;
387 log_info("Not all swaps are turned off, %d left.", r);
389 log_error("Failed to turn off swaps: %s", strerror(-r));
392 if (need_loop_detach) {
393 log_info("Detaching loop devices.");
394 r = loopback_detach_all(&changed);
396 need_loop_detach = false;
398 log_info("Not all loop devices detached, %d left.", r);
400 log_error("Failed to detach loop devices: %s", strerror(-r));
403 if (need_dm_detach) {
404 log_info("Detaching DM devices.");
405 r = dm_detach_all(&changed);
407 need_dm_detach = false;
409 log_warning("Not all DM devices detached, %d left.", r);
411 log_error("Failed to detach DM devices: %s", strerror(-r));
414 if (!need_umount && !need_swapoff && !need_loop_detach && !need_dm_detach) {
416 log_info("All filesystems, swaps, loop devices, DM devices detached.");
421 /* If in this iteration we didn't manage to
422 * unmount/deactivate anything, we either kill more
423 * processes, or simply give up */
426 if (killed_everbody) {
427 /* Hmm, we already killed everybody,
428 * let's just give up */
429 log_error("Cannot finalize remaining file systems and devices, giving up.");
433 log_warning("Cannot finalize remaining file systems and devices, trying to kill remaining processes.");
434 ultimate_send_signal(SIGTERM);
435 ultimate_send_signal(SIGKILL);
436 killed_everbody = true;
439 log_debug("Couldn't finalize remaining file systems and devices after %u retries, trying again.", retries+1);
442 if (retries >= FINALIZE_ATTEMPTS)
443 log_error("Too many iterations, giving up.");
445 execute_directory(SYSTEM_SHUTDOWN_PATH, NULL, NULL);
447 /* If we are in a container, just exit, this will kill our
448 * container for good. */
450 log_error("Exiting container.");
454 if (access("/run/initramfs/shutdown", X_OK) == 0) {
456 if (prepare_new_root() >= 0 &&
457 pivot_to_new_root() >= 0) {
458 execv("/shutdown", argv);
459 log_error("Failed to execute shutdown binary: %m");
465 if (cmd == LINUX_REBOOT_CMD_KEXEC) {
466 /* We cheat and exec kexec to avoid doing all its work */
470 log_error("Could not fork: %m. Falling back to normal reboot.");
472 wait_for_terminate_and_warn("kexec", pid);
473 log_warning("kexec failed. Falling back to normal reboot.");
476 const char *args[3] = { "/sbin/kexec", "-e", NULL };
477 execv(args[0], (char * const *) args);
485 log_error("Failed to invoke reboot(): %m");
489 log_error("Critical error while doing system shutdown: %s", strerror(-r));