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
1_10_stable
Denis Vlasenko 2007-12-26 18:32:58 +00:00
parent 5adfa44101
commit d55268d0d4
1 changed files with 47 additions and 39 deletions

View File

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