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_label(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) {
270 if (chdir("/run/initramfs") < 0) {
271 log_error("Failed to change directory to /run/initramfs: %m");
276 In case some evil process made "/" MS_SHARED
277 It works for pivot_root, but the ref count for the root device
278 is not decreasing :-/
280 if (mount(NULL, "/", NULL, MS_PRIVATE, NULL) < 0) {
281 log_error("Failed to make \"/\" private mount %m");
285 if (pivot_root(".", "oldroot") < 0) {
286 log_error("pivot failed: %m");
287 /* only chroot if pivot root succeded */
294 make_console_stdio();
296 log_info("Successfully changed into root pivot.");
301 int main(int argc, char *argv[]) {
304 bool need_umount = true, need_swapoff = true, need_loop_detach = true, need_dm_detach = true;
305 bool killed_everbody = false, in_container, use_watchdog = false;
308 log_parse_environment();
309 log_set_target(LOG_TARGET_CONSOLE); /* syslog will die if not gone yet */
315 log_error("Not executed by init (pid 1).");
321 log_error("Invalid number of arguments.");
326 in_container = detect_container(NULL) > 0;
328 if (streq(argv[1], "reboot"))
330 else if (streq(argv[1], "poweroff"))
332 else if (streq(argv[1], "halt"))
333 cmd = RB_HALT_SYSTEM;
334 else if (streq(argv[1], "kexec"))
335 cmd = LINUX_REBOOT_CMD_KEXEC;
337 log_error("Unknown action '%s'.", argv[1]);
342 use_watchdog = !!getenv("WATCHDOG_USEC");
344 /* lock us into memory */
345 mlockall(MCL_CURRENT|MCL_FUTURE);
347 log_info("Sending SIGTERM to remaining processes...");
348 send_signal(SIGTERM);
350 log_info("Sending SIGKILL to remaining processes...");
351 send_signal(SIGKILL);
354 need_swapoff = false;
355 need_dm_detach = false;
358 /* Unmount all mountpoints, swaps, and loopback devices */
359 for (retries = 0; retries < FINALIZE_ATTEMPTS; retries++) {
360 bool changed = false;
366 log_info("Unmounting file systems.");
367 r = umount_all(&changed);
371 log_info("Not all file systems unmounted, %d left.", r);
373 log_error("Failed to unmount file systems: %s", strerror(-r));
377 log_info("Disabling swaps.");
378 r = swapoff_all(&changed);
380 need_swapoff = false;
382 log_info("Not all swaps are turned off, %d left.", r);
384 log_error("Failed to turn off swaps: %s", strerror(-r));
387 if (need_loop_detach) {
388 log_info("Detaching loop devices.");
389 r = loopback_detach_all(&changed);
391 need_loop_detach = false;
393 log_info("Not all loop devices detached, %d left.", r);
395 log_error("Failed to detach loop devices: %s", strerror(-r));
398 if (need_dm_detach) {
399 log_info("Detaching DM devices.");
400 r = dm_detach_all(&changed);
402 need_dm_detach = false;
404 log_warning("Not all DM devices detached, %d left.", r);
406 log_error("Failed to detach DM devices: %s", strerror(-r));
409 if (!need_umount && !need_swapoff && !need_loop_detach && !need_dm_detach) {
411 log_info("All filesystems, swaps, loop devices, DM devices detached.");
416 /* If in this iteration we didn't manage to
417 * unmount/deactivate anything, we either kill more
418 * processes, or simply give up */
421 if (killed_everbody) {
422 /* Hmm, we already killed everybody,
423 * let's just give up */
424 log_error("Cannot finalize remaining file systems and devices, giving up.");
428 log_warning("Cannot finalize remaining file systems and devices, trying to kill remaining processes.");
429 ultimate_send_signal(SIGTERM);
430 ultimate_send_signal(SIGKILL);
431 killed_everbody = true;
434 log_debug("Couldn't finalize remaining file systems and devices after %u retries, trying again.", retries+1);
437 if (retries >= FINALIZE_ATTEMPTS)
438 log_error("Too many iterations, giving up.");
441 arguments[1] = argv[1];
443 execute_directory(SYSTEM_SHUTDOWN_PATH, NULL, arguments);
445 /* If we are in a container, just exit, this will kill our
446 * container for good. */
448 log_error("Exiting container.");
452 if (access("/run/initramfs/shutdown", X_OK) == 0) {
454 if (prepare_new_root() >= 0 &&
455 pivot_to_new_root() >= 0) {
456 execv("/shutdown", argv);
457 log_error("Failed to execute shutdown binary: %m");
463 if (cmd == LINUX_REBOOT_CMD_KEXEC) {
464 /* We cheat and exec kexec to avoid doing all its work */
468 log_error("Could not fork: %m. Falling back to normal reboot.");
470 wait_for_terminate_and_warn("kexec", pid);
471 log_warning("kexec failed. Falling back to normal reboot.");
474 const char *args[3] = { "/sbin/kexec", "-e", NULL };
475 execv(args[0], (char * const *) args);
483 log_error("Failed to invoke reboot(): %m");
487 log_error("Critical error while doing system shutdown: %s", strerror(-r));