aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2018-02-19 15:52:35 +0100
committerDenys Vlasenko <vda.linux@googlemail.com>2018-02-19 15:52:35 +0100
commit95121d98e6da12599246d8e25c3f300e422a06fb (patch)
treedcdb5306ba795ceccb9c435967ff535a949c3422
parent7398892ac0592999397532ba168376edd402438c (diff)
downloadbusybox-w32-95121d98e6da12599246d8e25c3f300e422a06fb.tar.gz
busybox-w32-95121d98e6da12599246d8e25c3f300e422a06fb.tar.bz2
busybox-w32-95121d98e6da12599246d8e25c3f300e422a06fb.zip
poweroff: add a config option for people needing VERY early poweroff
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r--init/halt.c54
1 files changed, 54 insertions, 0 deletions
diff --git a/init/halt.c b/init/halt.c
index c6c857f08..e6dcb1c67 100644
--- a/init/halt.c
+++ b/init/halt.c
@@ -24,6 +24,17 @@
24//config: help 24//config: help
25//config: Stop all processes and reboot the system. 25//config: Stop all processes and reboot the system.
26//config: 26//config:
27//config:config FEATURE_WAIT_FOR_INIT
28//config: bool "Before signaling init, make sure it is ready for it"
29//config: default y
30//config: depends on HALT || POWEROFF || REBOOT
31//config: help
32//config: In rare cases, poweroff may be commanded by firmware to OS
33//config: even before init process exists. On Linux, this spawns
34//config: "/sbin/poweroff" very early. This option adds code
35//config: which checks that init is ready to receive poweroff
36//config: commands. Code size increase of ~80 bytes.
37//config:
27//config:config FEATURE_CALL_TELINIT 38//config:config FEATURE_CALL_TELINIT
28//config: bool "Call telinit on shutdown and reboot" 39//config: bool "Call telinit on shutdown and reboot"
29//config: default y 40//config: default y
@@ -108,6 +119,47 @@ static void write_wtmp(void)
108#define write_wtmp() ((void)0) 119#define write_wtmp() ((void)0)
109#endif 120#endif
110 121
122#if ENABLE_FEATURE_WAIT_FOR_INIT
123/* In Linux, "poweroff" may be spawned even before init.
124 * For example, with ACPI:
125 * linux/drivers/acpi/bus.c:
126 * static void sb_notify_work(struct work_struct *dummy)
127 * orderly_poweroff(true);
128 * linux/kernel/reboot.c:
129 * static int run_cmd(const char *cmd)
130 * ret = call_usermodehelper(argv[0], argv, envp, UMH_WAIT_EXEC);
131 * poweroff_cmd[] = "/sbin/poweroff";
132 * static int __orderly_poweroff(bool force)
133 * ret = run_cmd(poweroff_cmd);
134 *
135 * We want to make sure init exists and listens to signals.
136 */
137static int init_was_not_there(void)
138{
139 enum { initial = 5 }; /* 5 seconds should be plenty for timeout */
140 int cnt = initial - 1;
141
142 /* Just existence of PID 1 does not mean it installed
143 * the handlers already.
144 */
145#if 0
146 while (kill(1, 0) != 0 && --cnt >= 0)
147 sleep(1);
148#endif
149 /* ... so let's wait for some evidence a usual startup event,
150 * mounting of /proc, happened. By that time init should be ready
151 * for signals.
152 */
153 while (access("/proc/meminfo", F_OK) != 0 && --cnt >= 0)
154 sleep(1);
155
156 /* Does it look like init wasn't there? */
157 return (cnt != initial - 1);
158}
159#else
160 /* Assume it's always there */
161# define init_was_not_there() 0
162#endif
111 163
112int halt_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 164int halt_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
113int halt_main(int argc UNUSED_PARAM, char **argv) 165int halt_main(int argc UNUSED_PARAM, char **argv)
@@ -171,6 +223,8 @@ int halt_main(int argc UNUSED_PARAM, char **argv)
171 if (!ENABLE_FEATURE_CALL_TELINIT) { 223 if (!ENABLE_FEATURE_CALL_TELINIT) {
172 /* bbox init assumed */ 224 /* bbox init assumed */
173 rc = kill(1, signals[which]); 225 rc = kill(1, signals[which]);
226 if (init_was_not_there())
227 rc = kill(1, signals[which]);
174 } else { 228 } else {
175 /* SysV style init assumed */ 229 /* SysV style init assumed */
176 /* runlevels: 230 /* runlevels: