Make it possible for service managers to differentiate a reboot vs
shutdown event.

Allows user to configure what should happen on SIGTERM (sent by
/sbin/reboot).

For example:

    ::shutdown:/sbin/openrc shutdown

If no shutdown action is specified in inittab, fall back to shutdown
action, so we don't break backwards compatibility.

downstream-issue: https://gitlab.alpinelinux.org/alpine/aports/-/issues/16695

function                                             old     new   delta
run                                                  256     686    +430
check_delayed_sigs                                   362     447     +85
run_actions                                          126     141     +15
static.actions                                        64      71      +7
parse_inittab                                        477     473      -4
reset_sighandlers_and_unblock_sigs                    22       -     -22
open_stdio_to_tty                                     85       -     -85
run_shutdown_and_kill_processes                      111       -    -111
init_exec                                            396       -    -396
------------------------------------------------------------------------------
(add/remove: 0/4 grow/shrink: 4/1 up/down: 537/-618)          Total: -81 bytes
   text    data     bss     dec     hex filename
 824050   14108    2008  840166   cd1e6 busybox_old
 823969   14108    2008  840085   cd195 busybox_unstripped

Signed-off-by: Natanael Copa <[email protected]>
---

Not sure why bloatcheck report that redicution in size. Was ran on
x86_64 with gcc 14 on Alpine Linux.


 init/init.c | 52 +++++++++++++++++++++++++++++++++++-----------------
 1 file changed, 35 insertions(+), 17 deletions(-)

diff --git a/init/init.c b/init/init.c
index 2ee1e4cde..47809a1e8 100644
--- a/init/init.c
+++ b/init/init.c
@@ -184,17 +184,27 @@
 /*
  * Start these before killing all processes in preparation for
  * running RESTART actions or doing low-level halt/reboot/poweroff
- * (initiated by SIGUSR1/SIGTERM/SIGUSR2).
+ * (initiated by SIGUSR1/SIGUSR2).
+ * Will also run as fallback if no REBOOT actions were execute on
+ * SIGTERM.
  * Wait for completion before proceeding.
  */
 #define SHUTDOWN    0x40
+/*
+ * Start these before killing all processes in preparation for
+ * doing low-level reboot (initiated by SIGTERM).
+ * If no reboot actions were executed, it will execute the SHUTDOWN
+ * actions as fallback.
+ * Wait for completion before proceeding.
+ */
+#define REBOOT      0x80
 /*
  * exec() on SIGQUIT. SHUTDOWN actions are started and waited for,
  * then all processes are killed, then init exec's 1st RESTART action,
  * replacing itself by it. If no RESTART action specified,
  * SIGQUIT has no effect.
  */
-#define RESTART     0x80
+#define RESTART     0x100
 
 /* A linked list of init_actions, to be read from inittab */
 struct init_action {
@@ -591,17 +601,19 @@ static void waitfor(pid_t pid)
 }
 
 /* Run all commands of a particular type */
-static void run_actions(int action_type)
+/* return 0 if no actions were run */
+static int run_actions(int action_type)
 {
        struct init_action *a;
+       pid_t pid = 0;
 
        for (a = G.init_action_list; a; a = a->next) {
                if (!(a->action_type & action_type))
                        continue;
 
-               if (a->action_type & (SYSINIT | WAIT | ONCE | CTRLALTDEL | 
SHUTDOWN)) {
-                       pid_t pid = run(a);
-                       if (a->action_type & (SYSINIT | WAIT | CTRLALTDEL | 
SHUTDOWN))
+               if (a->action_type & (SYSINIT | WAIT | ONCE | CTRLALTDEL | 
SHUTDOWN | REBOOT)) {
+                       pid = run(a);
+                       if (a->action_type & (SYSINIT | WAIT | CTRLALTDEL | 
SHUTDOWN | REBOOT))
                                waitfor(pid);
                }
                if (a->action_type & (RESPAWN | ASKFIRST)) {
@@ -612,9 +624,10 @@ static void run_actions(int action_type)
                                a->pid = run(a);
                }
        }
+       return pid != 0;
 }
 
-static void new_init_action(uint8_t action_type, const char *command, const 
char *cons)
+static void new_init_action(uint32_t action_type, const char *command, const 
char *cons)
 {
        struct init_action *a, **nextp;
 
@@ -705,7 +718,7 @@ static void parse_inittab(void)
                /* order must correspond to SYSINIT..RESTART constants */
                static const char actions[] ALIGN1 =
                        "sysinit\0""wait\0""once\0""respawn\0""askfirst\0"
-                       "ctrlaltdel\0""shutdown\0""restart\0";
+                       "ctrlaltdel\0""shutdown\0""reboot\0""restart\0";
                int action;
                char *tty = token[0];
 
@@ -755,12 +768,14 @@ static void pause_and_low_level_reboot(unsigned magic)
        _exit_SUCCESS();
 }
 
-static void run_shutdown_and_kill_processes(void)
+static void run_shutdown_and_kill_processes(int sig)
 {
        /* Run everything to be run at "shutdown".  This is done _prior_
         * to killing everything, in case people wish to use scripts to
         * shut things down gracefully... */
-       run_actions(SHUTDOWN);
+       if ((sig != SIGTERM) || (run_actions(REBOOT) == 0)) {
+               (void)run_actions(SHUTDOWN);
+       }
 
        message(L_CONSOLE | L_LOG, "The system is going down NOW!");
 
@@ -821,7 +836,7 @@ static void halt_reboot_pwoff(int sig)
         */
        reset_sighandlers_and_unblock_sigs();
 
-       run_shutdown_and_kill_processes();
+       run_shutdown_and_kill_processes(sig);
 
        m = "halt";
        rb = RB_HALT_SYSTEM;
@@ -854,7 +869,7 @@ static void exec_restart_action(void)
 
                reset_sighandlers_and_unblock_sigs();
 
-               run_shutdown_and_kill_processes();
+               run_shutdown_and_kill_processes(SIGQUIT);
 
 #ifdef RB_ENABLE_CAD
                /* Allow Ctrl-Alt-Del to reboot the system.
@@ -986,7 +1001,7 @@ static void check_delayed_sigs(struct timespec *ts)
                reload_inittab();
 #endif
        if (sig == SIGINT)
-               run_actions(CTRLALTDEL);
+               (void)run_actions(CTRLALTDEL);
        if (sig == SIGQUIT) {
                exec_restart_action();
                /* returns only if no restart action defined */
@@ -1179,18 +1194,18 @@ int init_main(int argc UNUSED_PARAM, char **argv)
 
        /* Now run everything that needs to be run */
        /* First run the sysinit command */
-       run_actions(SYSINIT);
+       (void)run_actions(SYSINIT);
        check_delayed_sigs(&G.zero_ts);
        /* Next run anything that wants to block */
-       run_actions(WAIT);
+       (void)run_actions(WAIT);
        check_delayed_sigs(&G.zero_ts);
        /* Next run anything to be run only once */
-       run_actions(ONCE);
+       (void)run_actions(ONCE);
 
        /* Now run the looping stuff for the rest of forever */
        while (1) {
                /* (Re)run the respawn/askfirst stuff */
-               run_actions(RESPAWN | ASKFIRST);
+               (void)run_actions(RESPAWN | ASKFIRST);
 
                /* Wait for any signal (typically it's SIGCHLD) */
                check_delayed_sigs(NULL); /* NULL timespec makes it wait */
@@ -1355,5 +1370,8 @@ int init_main(int argc UNUSED_PARAM, char **argv)
 //usage:       "       \n"
 //usage:       "       # Stuff to do before rebooting\n"
 //usage:       "       ::ctrlaltdel:/sbin/reboot\n"
+//usage:       "       ::reboot:/bin/umount -a -r\n"
+//usage:       "       ::reboot:/sbin/swapoff -a\n"
+//usage:       "       # Stuff to do before poweroff (also fallback when no 
reboot actions specified)\n"
 //usage:       "       ::shutdown:/bin/umount -a -r\n"
 //usage:       "       ::shutdown:/sbin/swapoff -a\n"
-- 
2.48.1

_______________________________________________
busybox mailing list
[email protected]
https://lists.busybox.net/mailman/listinfo/busybox

Reply via email to