From d55268d0d497856a34f732aca158d07276358ab6 Mon Sep 17 00:00:00 2001 From: Denis Vlasenko Date: Wed, 26 Dec 2007 18:32:58 +0000 Subject: [PATCH] init: don't spawn tons of waiting children, one is enough 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 | 86 +++++++++++++++++++++++++++++------------------------ 1 file changed, 47 insertions(+), 39 deletions(-) diff --git a/init/init.c b/init/init.c index 83678c1c3..51125f348 100644 --- a/init/init.c +++ b/init/init.c @@ -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);