init: do not run shutdown/reexec actions from signal handler
this is racy wrt various libc functions such as syslog()
function old new delta
check_delayed_sigs 182 352 +170
init_main 772 728 -44
restart_handler 74 - -74
halt_reboot_pwoff 79 - -79
------------------------------------------------------------------------------
(add/remove: 0/2 grow/shrink: 1/1 up/down: 170/-197) Total: -27 bytes
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
diff --git a/init/init.c b/init/init.c
index de438be..d99d68c 100644
--- a/init/init.c
+++ b/init/init.c
@@ -822,7 +822,7 @@
/* Handler for QUIT - exec "restart" action,
* else (no such action defined) do nothing */
-static void restart_handler(int sig UNUSED_PARAM)
+static void exec_restart_action(void)
{
struct init_action *a;
@@ -975,6 +975,20 @@
#endif
if (sig == SIGINT)
run_actions(CTRLALTDEL);
+ if (sig == SIGQUIT) {
+ exec_restart_action();
+ /* returns only if no restart action defined */
+ }
+ if ((1 << sig) & (0
+#ifdef SIGPWR
+ + (1 << SIGPWR)
+#endif
+ + (1 << SIGUSR1)
+ + (1 << SIGUSR2)
+ + (1 << SIGTERM)
+ )) {
+ halt_reboot_pwoff(sig);
+ }
}
}
@@ -1070,7 +1084,7 @@
#if 0
/* It's 2013, does anyone really still depend on this? */
-/* If you do, consider adding swapon to sysinot actions then! */
+/* If you do, consider adding swapon to sysinit actions then! */
/* struct sysinfo is linux-specific */
# ifdef __linux__
/* Make sure there is enough memory to do something useful. */
@@ -1134,16 +1148,6 @@
if (!DEBUG_INIT) {
struct sigaction sa;
- bb_signals(0
-#ifdef SIGPWR
- + (1 << SIGPWR) /* halt */
-#endif
- + (1 << SIGUSR1) /* halt */
- + (1 << SIGTERM) /* reboot */
- + (1 << SIGUSR2) /* poweroff */
- , halt_reboot_pwoff);
- signal(SIGQUIT, restart_handler); /* re-exec another init */
-
/* Stop handler must allow only SIGCONT inside itself */
memset(&sa, 0, sizeof(sa));
sigfillset(&sa.sa_mask);
@@ -1158,18 +1162,24 @@
*/
sigaction_set(SIGSTOP, &sa); /* pause */
- /* SIGINT (Ctrl-Alt-Del) must interrupt wait(),
+ /* These signals must interrupt wait(),
* setting handler without SA_RESTART flag.
*/
- bb_signals_recursive_norestart((1 << SIGINT), record_signo);
+ bb_signals_recursive_norestart(0
+ + (1 << SIGINT) /* Ctrl-Alt-Del */
+ + (1 << SIGQUIT) /* re-exec another init */
+#ifdef SIGPWR
+ + (1 << SIGPWR) /* halt */
+#endif
+ + (1 << SIGUSR1) /* halt */
+ + (1 << SIGTERM) /* reboot */
+ + (1 << SIGUSR2) /* poweroff */
+#if ENABLE_FEATURE_USE_INITTAB
+ + (1 << SIGHUP) /* reread /etc/inittab */
+#endif
+ , record_signo);
}
- /* Set up "reread /etc/inittab" handler.
- * Handler is set up without SA_RESTART, it will interrupt syscalls.
- */
- if (!DEBUG_INIT && ENABLE_FEATURE_USE_INITTAB)
- bb_signals_recursive_norestart((1 << SIGHUP), record_signo);
-
/* Now run everything that needs to be run */
/* First run the sysinit command */
run_actions(SYSINIT);