state: fix reboot causing shutdown inside LXC container
authorPetr Štetiar <ynezz@true.cz>
Wed, 15 Jan 2020 19:28:38 +0000 (20:28 +0100)
committerPetr Štetiar <ynezz@true.cz>
Tue, 21 Jan 2020 14:42:23 +0000 (15:42 +0100)
Executing `reboot` command in OpenWrt system runing inside LXC container
results in a shutdown of the container instead of rebooting the
container.

This appears to have been caused by commit 832369078d81 ("state: fix
shutdown when running in a container (FS#2425)"), which exits the pid
einz instead of the reboot().

While at it, refactor the halting code into separate function to shorten
the switch/case block and make it clearer, decrease the indentation
level by reversing the container if condition, replace magic 0 with
EXIT_SUCCESS constant in exit() and make it wait 1s for reboot message
delivery in both container/host cases as well.

Ref: FS#2666
Cc: Paul Spooren <mail@aparcar.org>
Fixes: 832369078d81 ("state: fix shutdown when running in a container (FS#2425)")
Tested-by: Baptiste Jonglez <lede@bitsofnetworks.org>
Signed-off-by: Petr Štetiar <ynezz@true.cz>
state.c

diff --git a/state.c b/state.c
index 4737d0121ad02a104549f4a0ca8c420486873c90..e117ea302f9301fea4e483b23c08676890f0ced4 100644 (file)
--- a/state.c
+++ b/state.c
@@ -94,6 +94,34 @@ static void set_console(void)
                set_stdio(tty);
 }
 
+static void perform_halt()
+{
+       if (reboot_event == RB_POWER_OFF)
+               LOG("- power down -\n");
+       else
+               LOG("- reboot -\n");
+
+       /* Allow time for last message to reach serial console, etc */
+       sleep(1);
+
+       if (is_container()) {
+               reboot(reboot_event);
+               exit(EXIT_SUCCESS);
+               return;
+       }
+
+       /* We have to fork here, since the kernel calls do_exit(EXIT_SUCCESS)
+        * in linux/kernel/sys.c, which can cause the machine to panic when
+        * the init process exits... */
+       if (!vfork()) { /* child */
+               reboot(reboot_event);
+               _exit(EXIT_SUCCESS);
+       }
+
+       while (1)
+               sleep(1);
+}
+
 static void state_enter(void)
 {
        char ubus_cmd[] = "/sbin/ubusd";
@@ -153,29 +181,9 @@ static void state_enter(void)
                sync();
                sleep(1);
 #ifndef DISABLE_INIT
-               if (reboot_event == RB_POWER_OFF)
-                       LOG("- power down -\n");
-               else
-                       LOG("- reboot -\n");
-
-               if (!is_container()) {
-                       /* Allow time for last message to reach serial console, etc */
-                       sleep(1);
-
-                       /* We have to fork here, since the kernel calls do_exit(EXIT_SUCCESS)
-                        * in linux/kernel/sys.c, which can cause the machine to panic when
-                        * the init process exits... */
-                       if (!vfork( )) { /* child */
-                               reboot(reboot_event);
-                               _exit(EXIT_SUCCESS);
-                       }
-
-                       while (1)
-                               sleep(1);
-               } else
-                       exit(0);
+               perform_halt();
 #else
-               exit(0);
+               exit(EXIT_SUCCESS);
 #endif
                break;