Add an abstract socket to synchronize the readiness of init to receive the SIGUSR2 to catch poweroff/reboot during an IPL phase (e.g. soft power off via BMC).
Signed-off-by: Deb McLemore <[email protected]> --- include/libbb.h | 5 +++++ init/halt.c | 33 +++++++++++++++++++++++++++++++++ init/init.c | 22 ++++++++++++++++++++++ 3 files changed, 60 insertions(+) diff --git a/include/libbb.h b/include/libbb.h index daccf15..9f9bfc2 100644 --- a/include/libbb.h +++ b/include/libbb.h @@ -174,6 +174,11 @@ # define STRERROR_ERRNO ,strerror(errno) #endif +#ifdef __linux +#define BB_SIGNALS_SOCKET_STRING "\0bb_signals" +#define BB_SIGNALS_SOCKET_STR_LEN 11 +#endif + /* Some libc's forget to declare these, do it ourself */ diff --git a/init/halt.c b/init/halt.c index c6c857f..47252e6 100644 --- a/init/halt.c +++ b/init/halt.c @@ -83,6 +83,10 @@ #include "libbb.h" #include "reboot.h" +#ifdef __linux__ +#include <sys/un.h> +#endif + #if ENABLE_FEATURE_WTMP #include <sys/utsname.h> @@ -112,6 +116,13 @@ static void write_wtmp(void) int halt_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; int halt_main(int argc UNUSED_PARAM, char **argv) { + +#ifdef __linux__ + struct sockaddr_un bb_addr2 = { .sun_family = AF_UNIX, + .sun_path = BB_SIGNALS_SOCKET_STRING }; + int fdBB2 = 0; + int fdrc = 0; +#endif static const int magic[] = { RB_HALT_SYSTEM, RB_POWER_OFF, @@ -170,6 +181,28 @@ int halt_main(int argc UNUSED_PARAM, char **argv) /* talk to init */ if (!ENABLE_FEATURE_CALL_TELINIT) { /* bbox init assumed */ + + /* Use socket connect to INIT to assure that + * signal handlers are ready + */ + #ifdef __linux__ + while (1) { + fdBB2 = socket(AF_UNIX, + SOCK_CLOEXEC | SOCK_DGRAM, 0); + if (fdBB2 != -1) + break; + sleep(1); + } + while (1) { + fdrc = connect(fdBB2, + (struct sockaddr *)&bb_addr2, + sizeof(sa_family_t) + + BB_SIGNALS_SOCKET_STR_LEN); + if (fdrc == 0) + break; + sleep(1); + } + #endif rc = kill(1, signals[which]); } else { /* SysV style init assumed */ diff --git a/init/init.c b/init/init.c index 6f3374e..4461fb6 100644 --- a/init/init.c +++ b/init/init.c @@ -133,6 +133,7 @@ #ifdef __linux__ # include <linux/vt.h> # include <sys/sysinfo.h> +# include <sys/un.h> #endif #include "reboot.h" /* reboot() constants */ @@ -1046,6 +1047,13 @@ static void sleep_much(void) int init_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; int init_main(int argc UNUSED_PARAM, char **argv) { + +#ifdef __linux__ + struct sockaddr_un bb_addr = { .sun_family = AF_UNIX, + .sun_path = BB_SIGNALS_SOCKET_STRING }; + int fdBB = 0; +#endif + if (argv[1] && strcmp(argv[1], "-q") == 0) { return kill(1, SIGHUP); } @@ -1191,6 +1199,20 @@ int init_main(int argc UNUSED_PARAM, char **argv) sigprocmask_allsigs(SIG_UNBLOCK); } +#ifdef __linux__ + /* Create an abstract socket to use for synchronizing poweroff and + * reboot which could be kicked at IPL before the INIT process + * completes signal setup to listen for the signals + * Ignore failures and keep on, this just helps + * close the exposed window when nothing will get signaled + * The abstract socket needs to stay persistent, so no cleanup + */ + fdBB = socket(AF_UNIX, SOCK_CLOEXEC | SOCK_DGRAM, 0); + if (fdBB != -1) + bind(fdBB, (struct sockaddr *)&bb_addr, + sizeof(sa_family_t) + BB_SIGNALS_SOCKET_STR_LEN); +#endif + /* Now run everything that needs to be run */ /* First run the sysinit command */ run_actions(SYSINIT); -- 2.7.4 _______________________________________________ busybox mailing list [email protected] http://lists.busybox.net/mailman/listinfo/busybox
