init: don't spawn tons of waiting children, one is enough
authorDenis Vlasenko <vda.linux@googlemail.com>
Wed, 26 Dec 2007 18:32:58 +0000 (18:32 -0000)
committerDenis Vlasenko <vda.linux@googlemail.com>
Wed, 26 Dec 2007 18:32:58 +0000 (18:32 -0000)
init: shrink signal disabling code
init: rename some functions
   text    data     bss     dec     hex filename
 778657     832    7344  786833   c0191 busybox_old
 778445     832    7344  786621   c00bd busybox_unstripped

init/init.c

index 83678c1..51125f3 100644 (file)
@@ -96,8 +96,9 @@ static const char *const environment[] = {
 /* Function prototypes */
 static void delete_init_action(struct init_action *a);
 static int waitfor(pid_t pid);
-static void shutdown_signal(int sig);
+static void halt_reboot_pwoff(int sig) ATTRIBUTE_NORETURN;
 
+static void loop_forever(void) ATTRIBUTE_NORETURN;
 static void loop_forever(void)
 {
        while (1)
@@ -259,26 +260,25 @@ static void set_sane_term(void)
 }
 
 /* Open the new terminal device */
-static void open_stdio_to_tty(const char* tty_name, int fail)
+static void open_stdio_to_tty(const char* tty_name, int exit_on_failure)
 {
        /* empty tty_name means "use init's tty", else... */
        if (tty_name[0]) {
-               int fd = device_open(tty_name, O_RDWR);
-               if (fd < 0) {
+               int fd;
+               close(0);
+               /* fd can be only < 0 or 0: */
+               fd = device_open(tty_name, O_RDWR);
+               if (fd) {
                        message(L_LOG | L_CONSOLE, "Can't open %s: %s",
                                tty_name, strerror(errno));
-                       if (fail)
+                       if (exit_on_failure)
                                _exit(1);
-                       if (!ENABLE_DEBUG_INIT)
-                               shutdown_signal(SIGUSR1);
-                       else
+                       if (ENABLE_DEBUG_INIT)
                                _exit(2);
-               } else {
-                       dup2(fd, 0);
-                       dup2(fd, 1);
-                       dup2(fd, 2);
-                       if (fd > 2) close(fd);
+                       halt_reboot_pwoff(SIGUSR1); /* halt the system */
                }
+               dup2(0, 1);
+               dup2(0, 2);
        }
        set_sane_term();
 }
@@ -412,9 +412,7 @@ static pid_t run(const struct init_action *a)
                }
 #endif
 
-               /* Establish this process as session leader and
-                * _attempt_ to make stdin a controlling tty.
-                */
+               /* _Attempt_ to make stdin a controlling tty. */
                if (ENABLE_FEATURE_INIT_SCTTY)
                        ioctl(0, TIOCSCTTY, 0 /*only try, don't steal*/);
        }
@@ -525,7 +523,7 @@ static void init_reboot(unsigned long magic)
        waitpid(pid, NULL, 0);
 }
 
-static void shutdown_system(void)
+static void kill_all_processes(void)
 {
        sigset_t block_signals;
 
@@ -535,7 +533,8 @@ static void shutdown_system(void)
        run_actions(SHUTDOWN);
 
        /* first disable all our signals */
-       sigemptyset(&block_signals);
+       sigfillset(&block_signals);
+       /*sigemptyset(&block_signals);
        sigaddset(&block_signals, SIGHUP);
        sigaddset(&block_signals, SIGQUIT);
        sigaddset(&block_signals, SIGCHLD);
@@ -545,7 +544,7 @@ static void shutdown_system(void)
        sigaddset(&block_signals, SIGTERM);
        sigaddset(&block_signals, SIGCONT);
        sigaddset(&block_signals, SIGSTOP);
-       sigaddset(&block_signals, SIGTSTP);
+       sigaddset(&block_signals, SIGTSTP);*/
        sigprocmask(SIG_BLOCK, &block_signals, NULL);
 
        message(L_CONSOLE | L_LOG, "The system is going down NOW!");
@@ -565,12 +564,12 @@ static void shutdown_system(void)
        sleep(1);
 }
 
-static void shutdown_signal(int sig)
+static void halt_reboot_pwoff(int sig)
 {
        const char *m;
        int rb;
 
-       shutdown_system();
+       kill_all_processes();
 
        m = "halt";
        rb = RB_HALT_SYSTEM;
@@ -588,7 +587,9 @@ static void shutdown_signal(int sig)
        loop_forever();
 }
 
-static void exec_signal(int sig ATTRIBUTE_UNUSED)
+/* Handler for HUP and QUIT - exec "restart" action,
+ * else (no such action defined) do nothing */
+static void exec_restart_action(int sig ATTRIBUTE_UNUSED)
 {
        struct init_action *a, *tmp;
        sigset_t unblock_signals;
@@ -596,10 +597,11 @@ static void exec_signal(int sig ATTRIBUTE_UNUSED)
        for (a = init_action_list; a; a = tmp) {
                tmp = a->next;
                if (a->action & RESTART) {
-                       shutdown_system();
+                       kill_all_processes();
 
-                       /* unblock all signals, blocked in shutdown_system() */
-                       sigemptyset(&unblock_signals);
+                       /* unblock all signals (blocked in kill_all_processes()) */
+                       sigfillset(&unblock_signals);
+                       /*sigemptyset(&unblock_signals);
                        sigaddset(&unblock_signals, SIGHUP);
                        sigaddset(&unblock_signals, SIGQUIT);
                        sigaddset(&unblock_signals, SIGCHLD);
@@ -609,11 +611,11 @@ static void exec_signal(int sig ATTRIBUTE_UNUSED)
                        sigaddset(&unblock_signals, SIGTERM);
                        sigaddset(&unblock_signals, SIGCONT);
                        sigaddset(&unblock_signals, SIGSTOP);
-                       sigaddset(&unblock_signals, SIGTSTP);
+                       sigaddset(&unblock_signals, SIGTSTP);*/
                        sigprocmask(SIG_UNBLOCK, &unblock_signals, NULL);
 
                        /* Open the new terminal device */
-                       open_stdio_to_tty(a->terminal, 0 /* - shutdown_signal(SIGUSR1) [halt] if open fails */);
+                       open_stdio_to_tty(a->terminal, 0 /* - halt if open fails */);
 
                        messageD(L_CONSOLE | L_LOG, "Trying to re-exec %s", a->command);
                        BB_EXECLP(a->command, a->command, NULL);
@@ -812,19 +814,25 @@ static void reload_signal(int sig ATTRIBUTE_UNUSED)
        parse_inittab();
 
        if (ENABLE_FEATURE_KILL_REMOVED) {
+               /* Be nice and send SIGTERM first */
                for (a = init_action_list; a; a = a->next) {
                        pid_t pid = a->pid;
                        if ((a->action & ONCE) && pid != 0) {
-                               /* Be nice and send SIGTERM first */
                                kill(pid, SIGTERM);
-                               if (CONFIG_FEATURE_KILL_DELAY)
-                                       if (fork() == 0) { /* child */
-                                               sleep(CONFIG_FEATURE_KILL_DELAY);
-                                               kill(pid, SIGKILL);
-                                               _exit(0);
-                                       }
                        }
                }
+#if CONFIG_FEATURE_KILL_DELAY
+               if (fork() == 0) { /* child */
+                       sleep(CONFIG_FEATURE_KILL_DELAY);
+                       for (a = init_action_list; a; a = a->next) {
+                               pid_t pid = a->pid;
+                               if ((a->action & ONCE) && pid != 0) {
+                                       kill(pid, SIGKILL);
+                               }
+                       }
+                       _exit(0);
+               }
+#endif
        }
 
        /* remove unused entrys */
@@ -858,12 +866,12 @@ int init_main(int argc, char **argv)
                }
                /* Set up sig handlers  -- be sure to
                 * clear all of these in run() */
-               signal(SIGHUP, exec_signal);
-               signal(SIGQUIT, exec_signal);
-               signal(SIGUSR1, shutdown_signal);
-               signal(SIGUSR2, shutdown_signal);
+               signal(SIGHUP, exec_restart_action);
+               signal(SIGQUIT, exec_restart_action);
+               signal(SIGUSR1, halt_reboot_pwoff); /* halt */
+               signal(SIGUSR2, halt_reboot_pwoff); /* poweroff */
+               signal(SIGTERM, halt_reboot_pwoff); /* reboot */
                signal(SIGINT, ctrlaltdel_signal);
-               signal(SIGTERM, shutdown_signal);
                signal(SIGCONT, cont_handler);
                signal(SIGSTOP, stop_handler);
                signal(SIGTSTP, stop_handler);