diff options
author | Denys Vlasenko <vda.linux@googlemail.com> | 2018-02-19 15:52:35 +0100 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2018-02-19 15:52:35 +0100 |
commit | 95121d98e6da12599246d8e25c3f300e422a06fb (patch) | |
tree | dcdb5306ba795ceccb9c435967ff535a949c3422 | |
parent | 7398892ac0592999397532ba168376edd402438c (diff) | |
download | busybox-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.c | 54 |
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 | */ | ||
137 | static 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 | ||
112 | int halt_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | 164 | int halt_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; |
113 | int halt_main(int argc UNUSED_PARAM, char **argv) | 165 | int 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: |