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

Reply via email to