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
diff --git a/init/init.c b/init/init.c
index 83678c1..51125f3 100644
--- a/init/init.c
+++ b/init/init.c
@@ -96,8 +96,9 @@
/* 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 @@
}
/* 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 @@
}
#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 @@
waitpid(pid, NULL, 0);
}
-static void shutdown_system(void)
+static void kill_all_processes(void)
{
sigset_t block_signals;
@@ -535,7 +533,8 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
}
/* 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);