blob: af7e75ba761fb813a386485e6522d7b6b53e7c41 [file] [log] [blame]
Denis Vlasenko8a164052007-03-12 23:34:52 +00001/*
2Copyright (c) 2001-2006, Gerrit Pape
3All rights reserved.
4
5Redistribution and use in source and binary forms, with or without
6modification, are permitted provided that the following conditions are met:
7
8 1. Redistributions of source code must retain the above copyright notice,
9 this list of conditions and the following disclaimer.
10 2. Redistributions in binary form must reproduce the above copyright
11 notice, this list of conditions and the following disclaimer in the
12 documentation and/or other materials provided with the distribution.
13 3. The name of the author may not be used to endorse or promote products
14 derived from this software without specific prior written permission.
15
16THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
17WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
19EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
22OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
23WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
25ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26*/
27
Denis Vlasenkod18f52b2008-03-02 12:53:15 +000028/* Busyboxed by Denys Vlasenko <vda.linux@googlemail.com> */
Denis Vlasenko04c63862006-11-17 18:58:49 +000029/* TODO: depends on runit_lib.c - review and reduce/eliminate */
30
Pere Orga5bc8c002011-04-11 03:29:49 +020031//usage:#define runsvdir_trivial_usage
32//usage: "[-P] [-s SCRIPT] DIR"
33//usage:#define runsvdir_full_usage "\n\n"
34//usage: "Start a runsv process for each subdirectory. If it exits, restart it.\n"
35//usage: "\n -P Put each runsv in a new session"
36//usage: "\n -s SCRIPT Run SCRIPT <signo> after signal is processed"
37
Denis Vlasenko04c63862006-11-17 18:58:49 +000038#include <sys/file.h>
Denis Vlasenkob6adbf12007-05-26 19:00:18 +000039#include "libbb.h"
Denis Vlasenko04c63862006-11-17 18:58:49 +000040#include "runit_lib.h"
41
42#define MAXSERVICES 1000
43
Denis Vlasenko923a79a2008-09-22 21:34:24 +000044/* Should be not needed - all dirs are on same FS, right? */
45#define CHECK_DEVNO_TOO 0
46
Denis Vlasenko45946f82007-08-20 17:27:40 +000047struct service {
Denis Vlasenko923a79a2008-09-22 21:34:24 +000048#if CHECK_DEVNO_TOO
Denis Vlasenko45946f82007-08-20 17:27:40 +000049 dev_t dev;
Denis Vlasenko923a79a2008-09-22 21:34:24 +000050#endif
Denis Vlasenko45946f82007-08-20 17:27:40 +000051 ino_t ino;
52 pid_t pid;
53 smallint isgone;
54};
55
Denis Vlasenkod0a071a2008-03-17 09:33:45 +000056struct globals {
57 struct service *sv;
58 char *svdir;
Denis Vlasenkod0a071a2008-03-17 09:33:45 +000059 int svnum;
Denis Vlasenko923a79a2008-09-22 21:34:24 +000060#if ENABLE_FEATURE_RUNSVDIR_LOG
61 char *rplog;
Denis Vlasenkod0a071a2008-03-17 09:33:45 +000062 int rploglen;
63 struct fd_pair logpipe;
64 struct pollfd pfd[1];
65 unsigned stamplog;
Denis Vlasenko923a79a2008-09-22 21:34:24 +000066#endif
Denys Vlasenko98a4c7c2010-02-04 15:00:15 +010067} FIX_ALIASING;
Denis Vlasenkod0a071a2008-03-17 09:33:45 +000068#define G (*(struct globals*)&bb_common_bufsiz1)
Denis Vlasenko923a79a2008-09-22 21:34:24 +000069#define sv (G.sv )
70#define svdir (G.svdir )
71#define svnum (G.svnum )
72#define rplog (G.rplog )
73#define rploglen (G.rploglen )
74#define logpipe (G.logpipe )
75#define pfd (G.pfd )
76#define stamplog (G.stamplog )
Denys Vlasenko16714242011-09-21 01:59:15 +020077#define INIT_G() do { } while (0)
Denis Vlasenko04c63862006-11-17 18:58:49 +000078
Denis Vlasenkoab2aea42007-01-29 22:51:58 +000079static void fatal2_cannot(const char *m1, const char *m2)
Denis Vlasenko04c63862006-11-17 18:58:49 +000080{
Denys Vlasenko6331cf02009-11-13 09:08:27 +010081 bb_perror_msg_and_die("%s: fatal: can't %s%s", svdir, m1, m2);
Denis Vlasenko04c63862006-11-17 18:58:49 +000082 /* was exiting 100 */
83}
Denis Vlasenkoab2aea42007-01-29 22:51:58 +000084static void warn3x(const char *m1, const char *m2, const char *m3)
Denis Vlasenko04c63862006-11-17 18:58:49 +000085{
86 bb_error_msg("%s: warning: %s%s%s", svdir, m1, m2, m3);
Denis Vlasenkof7996f32007-01-11 17:20:00 +000087}
Denis Vlasenkoab2aea42007-01-29 22:51:58 +000088static void warn2_cannot(const char *m1, const char *m2)
Denis Vlasenko04c63862006-11-17 18:58:49 +000089{
Denys Vlasenko6331cf02009-11-13 09:08:27 +010090 warn3x("can't ", m1, m2);
Denis Vlasenko04c63862006-11-17 18:58:49 +000091}
Denis Vlasenko923a79a2008-09-22 21:34:24 +000092#if ENABLE_FEATURE_RUNSVDIR_LOG
Denis Vlasenkoab2aea42007-01-29 22:51:58 +000093static void warnx(const char *m1)
Denis Vlasenko04c63862006-11-17 18:58:49 +000094{
95 warn3x(m1, "", "");
Denis Vlasenkof7996f32007-01-11 17:20:00 +000096}
Denis Vlasenko923a79a2008-09-22 21:34:24 +000097#endif
Denis Vlasenko04c63862006-11-17 18:58:49 +000098
Denis Vlasenko6a2c2cf2008-10-29 12:04:45 +000099/* inlining + vfork -> bigger code */
100static NOINLINE pid_t runsv(const char *name)
Denis Vlasenko04c63862006-11-17 18:58:49 +0000101{
Denis Vlasenko6a2c2cf2008-10-29 12:04:45 +0000102 pid_t pid;
Denis Vlasenko04c63862006-11-17 18:58:49 +0000103
Denis Vlasenko6a2c2cf2008-10-29 12:04:45 +0000104 /* If we got signaled, stop spawning children at once! */
105 if (bb_got_signal)
106 return 0;
107
108 pid = vfork();
Denis Vlasenko04c63862006-11-17 18:58:49 +0000109 if (pid == -1) {
Denis Vlasenko45946f82007-08-20 17:27:40 +0000110 warn2_cannot("vfork", "");
Denis Vlasenko6a2c2cf2008-10-29 12:04:45 +0000111 return 0;
Denis Vlasenko04c63862006-11-17 18:58:49 +0000112 }
113 if (pid == 0) {
114 /* child */
Denis Vlasenko3854c5d2008-11-06 22:39:57 +0000115 if (option_mask32 & 1) /* -P option? */
Denis Vlasenko2856dab2007-04-01 01:18:20 +0000116 setsid();
Denis Vlasenko96575962008-10-29 03:42:44 +0000117/* man execv:
Denis Vlasenko6a2c2cf2008-10-29 12:04:45 +0000118 * "Signals set to be caught by the calling process image
119 * shall be set to the default action in the new process image."
Denis Vlasenko96575962008-10-29 03:42:44 +0000120 * Therefore, we do not need this: */
121#if 0
Denis Vlasenko25591c32008-02-16 22:58:56 +0000122 bb_signals(0
Denis Vlasenko96575962008-10-29 03:42:44 +0000123 | (1 << SIGHUP)
124 | (1 << SIGTERM)
Denis Vlasenko25591c32008-02-16 22:58:56 +0000125 , SIG_DFL);
Denis Vlasenko96575962008-10-29 03:42:44 +0000126#endif
Denis Vlasenkof09f4e02009-02-26 12:29:59 +0000127 execlp("runsv", "runsv", name, (char *) NULL);
Denis Vlasenko04c63862006-11-17 18:58:49 +0000128 fatal2_cannot("start runsv ", name);
129 }
Denis Vlasenko6a2c2cf2008-10-29 12:04:45 +0000130 return pid;
Denis Vlasenko04c63862006-11-17 18:58:49 +0000131}
132
Denis Vlasenko6a2c2cf2008-10-29 12:04:45 +0000133/* gcc 4.3.0 does better with NOINLINE */
134static NOINLINE int do_rescan(void)
Denis Vlasenko04c63862006-11-17 18:58:49 +0000135{
136 DIR *dir;
Denys Vlasenkoaebb7422009-08-02 00:55:49 +0200137 struct dirent *d;
Denis Vlasenko04c63862006-11-17 18:58:49 +0000138 int i;
139 struct stat s;
Denis Vlasenko6a2c2cf2008-10-29 12:04:45 +0000140 int need_rescan = 0;
Denis Vlasenko04c63862006-11-17 18:58:49 +0000141
142 dir = opendir(".");
143 if (!dir) {
144 warn2_cannot("open directory ", svdir);
Denis Vlasenko6a2c2cf2008-10-29 12:04:45 +0000145 return 1; /* need to rescan again soon */
Denis Vlasenko04c63862006-11-17 18:58:49 +0000146 }
147 for (i = 0; i < svnum; i++)
148 sv[i].isgone = 1;
Denis Vlasenko8f740942008-05-31 07:00:33 +0000149
150 while (1) {
151 errno = 0;
152 d = readdir(dir);
153 if (!d)
154 break;
Denis Vlasenko45946f82007-08-20 17:27:40 +0000155 if (d->d_name[0] == '.')
156 continue;
Denis Vlasenko04c63862006-11-17 18:58:49 +0000157 if (stat(d->d_name, &s) == -1) {
158 warn2_cannot("stat ", d->d_name);
Denis Vlasenko04c63862006-11-17 18:58:49 +0000159 continue;
160 }
Denis Vlasenko45946f82007-08-20 17:27:40 +0000161 if (!S_ISDIR(s.st_mode))
162 continue;
Denis Vlasenko6a2c2cf2008-10-29 12:04:45 +0000163 /* Do we have this service listed already? */
Denis Vlasenko04c63862006-11-17 18:58:49 +0000164 for (i = 0; i < svnum; i++) {
Denis Vlasenko923a79a2008-09-22 21:34:24 +0000165 if ((sv[i].ino == s.st_ino)
166#if CHECK_DEVNO_TOO
167 && (sv[i].dev == s.st_dev)
168#endif
169 ) {
Denis Vlasenko6a2c2cf2008-10-29 12:04:45 +0000170 if (sv[i].pid == 0) /* restart if it has died */
171 goto run_ith_sv;
172 sv[i].isgone = 0; /* "we still see you" */
173 goto next_dentry;
Denis Vlasenko04c63862006-11-17 18:58:49 +0000174 }
175 }
Denis Vlasenko6a2c2cf2008-10-29 12:04:45 +0000176 { /* Not found, make new service */
Denis Vlasenko04c63862006-11-17 18:58:49 +0000177 struct service *svnew = realloc(sv, (i+1) * sizeof(*sv));
178 if (!svnew) {
Denis Vlasenko923a79a2008-09-22 21:34:24 +0000179 warn2_cannot("start runsv ", d->d_name);
Denis Vlasenko6a2c2cf2008-10-29 12:04:45 +0000180 need_rescan = 1;
Denis Vlasenko04c63862006-11-17 18:58:49 +0000181 continue;
182 }
183 sv = svnew;
184 svnum++;
Denis Vlasenko923a79a2008-09-22 21:34:24 +0000185#if CHECK_DEVNO_TOO
Denis Vlasenko04c63862006-11-17 18:58:49 +0000186 sv[i].dev = s.st_dev;
Denis Vlasenko923a79a2008-09-22 21:34:24 +0000187#endif
Denis Vlasenko6a2c2cf2008-10-29 12:04:45 +0000188 sv[i].ino = s.st_ino;
189 run_ith_sv:
190 sv[i].pid = runsv(d->d_name);
191 sv[i].isgone = 0;
Denis Vlasenko04c63862006-11-17 18:58:49 +0000192 }
Denis Vlasenko6a2c2cf2008-10-29 12:04:45 +0000193 next_dentry: ;
Denis Vlasenko04c63862006-11-17 18:58:49 +0000194 }
Denis Vlasenko923a79a2008-09-22 21:34:24 +0000195 i = errno;
196 closedir(dir);
Denis Vlasenko6a2c2cf2008-10-29 12:04:45 +0000197 if (i) { /* readdir failed */
Denis Vlasenko04c63862006-11-17 18:58:49 +0000198 warn2_cannot("read directory ", svdir);
Denis Vlasenko6a2c2cf2008-10-29 12:04:45 +0000199 return 1; /* need to rescan again soon */
Denis Vlasenko04c63862006-11-17 18:58:49 +0000200 }
Denis Vlasenko04c63862006-11-17 18:58:49 +0000201
Denis Vlasenko6a2c2cf2008-10-29 12:04:45 +0000202 /* Send SIGTERM to runsv whose directories
203 * were no longer found (-> must have been removed) */
Denis Vlasenko04c63862006-11-17 18:58:49 +0000204 for (i = 0; i < svnum; i++) {
205 if (!sv[i].isgone)
206 continue;
207 if (sv[i].pid)
208 kill(sv[i].pid, SIGTERM);
Denis Vlasenko923a79a2008-09-22 21:34:24 +0000209 svnum--;
210 sv[i] = sv[svnum];
211 i--; /* so that we don't skip new sv[i] (bug was here!) */
Denis Vlasenko04c63862006-11-17 18:58:49 +0000212 }
Denis Vlasenko6a2c2cf2008-10-29 12:04:45 +0000213 return need_rescan;
Denis Vlasenko04c63862006-11-17 18:58:49 +0000214}
215
Denis Vlasenko9b49a5e2007-10-11 10:05:36 +0000216int runsvdir_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
Denis Vlasenkoa60f84e2008-07-05 09:18:54 +0000217int runsvdir_main(int argc UNUSED_PARAM, char **argv)
Denis Vlasenko04c63862006-11-17 18:58:49 +0000218{
219 struct stat s;
Denis Vlasenko45946f82007-08-20 17:27:40 +0000220 dev_t last_dev = last_dev; /* for gcc */
221 ino_t last_ino = last_ino; /* for gcc */
222 time_t last_mtime = 0;
Denis Vlasenko04c63862006-11-17 18:58:49 +0000223 int wstat;
224 int curdir;
Denis Vlasenko3854c5d2008-11-06 22:39:57 +0000225 pid_t pid;
Denis Vlasenko45946f82007-08-20 17:27:40 +0000226 unsigned deadline;
227 unsigned now;
228 unsigned stampcheck;
Denis Vlasenko04c63862006-11-17 18:58:49 +0000229 int i;
Denis Vlasenko6a2c2cf2008-10-29 12:04:45 +0000230 int need_rescan = 1;
Denis Vlasenko3854c5d2008-11-06 22:39:57 +0000231 char *opt_s_argv[3];
Denis Vlasenko04c63862006-11-17 18:58:49 +0000232
Denis Vlasenkod0a071a2008-03-17 09:33:45 +0000233 INIT_G();
234
Denis Vlasenko08ea11a2008-09-11 19:51:11 +0000235 opt_complementary = "-1";
Denis Vlasenko3854c5d2008-11-06 22:39:57 +0000236 opt_s_argv[0] = NULL;
237 opt_s_argv[2] = NULL;
238 getopt32(argv, "Ps:", &opt_s_argv[0]);
Denis Vlasenko08ea11a2008-09-11 19:51:11 +0000239 argv += optind;
Denis Vlasenko04c63862006-11-17 18:58:49 +0000240
Denis Vlasenko96575962008-10-29 03:42:44 +0000241 bb_signals(0
242 | (1 << SIGTERM)
243 | (1 << SIGHUP)
244 /* For busybox's init, SIGTERM == reboot,
245 * SIGUSR1 == halt
246 * SIGUSR2 == poweroff
247 * so we need to intercept SIGUSRn too.
248 * Note that we do not implement actual reboot
249 * (killall(TERM) + umount, etc), we just pause
250 * respawing and avoid exiting (-> making kernel oops).
251 * The user is responsible for the rest. */
252 | (getpid() == 1 ? ((1 << SIGUSR1) | (1 << SIGUSR2)) : 0)
253 , record_signo);
Denis Vlasenko04c63862006-11-17 18:58:49 +0000254 svdir = *argv++;
Denis Vlasenko923a79a2008-09-22 21:34:24 +0000255
256#if ENABLE_FEATURE_RUNSVDIR_LOG
257 /* setup log */
258 if (*argv) {
Denis Vlasenko04c63862006-11-17 18:58:49 +0000259 rplog = *argv;
Denis Vlasenko923a79a2008-09-22 21:34:24 +0000260 rploglen = strlen(rplog);
261 if (rploglen < 7) {
262 warnx("log must have at least seven characters");
263 } else if (piped_pair(logpipe)) {
Denys Vlasenko6331cf02009-11-13 09:08:27 +0100264 warnx("can't create pipe for log");
Denis Vlasenko923a79a2008-09-22 21:34:24 +0000265 } else {
266 close_on_exec_on(logpipe.rd);
267 close_on_exec_on(logpipe.wr);
268 ndelay_on(logpipe.rd);
269 ndelay_on(logpipe.wr);
270 if (dup2(logpipe.wr, 2) == -1) {
Denys Vlasenko6331cf02009-11-13 09:08:27 +0100271 warnx("can't set filedescriptor for log");
Denis Vlasenko923a79a2008-09-22 21:34:24 +0000272 } else {
273 pfd[0].fd = logpipe.rd;
274 pfd[0].events = POLLIN;
275 stamplog = monotonic_sec();
276 goto run;
277 }
Denis Vlasenko04c63862006-11-17 18:58:49 +0000278 }
Denis Vlasenko923a79a2008-09-22 21:34:24 +0000279 rplog = NULL;
280 warnx("log service disabled");
Denis Vlasenko04c63862006-11-17 18:58:49 +0000281 }
Denis Vlasenko96575962008-10-29 03:42:44 +0000282 run:
Denis Vlasenko923a79a2008-09-22 21:34:24 +0000283#endif
Denys Vlasenko05e86052010-10-13 12:53:27 +0200284 curdir = open(".", O_RDONLY|O_NDELAY);
Denis Vlasenkof7996f32007-01-11 17:20:00 +0000285 if (curdir == -1)
Denis Vlasenko04c63862006-11-17 18:58:49 +0000286 fatal2_cannot("open current directory", "");
Denis Vlasenko96e1b382007-09-30 23:50:48 +0000287 close_on_exec_on(curdir);
Denis Vlasenko04c63862006-11-17 18:58:49 +0000288
Denis Vlasenko45946f82007-08-20 17:27:40 +0000289 stampcheck = monotonic_sec();
Denis Vlasenko04c63862006-11-17 18:58:49 +0000290
291 for (;;) {
292 /* collect children */
293 for (;;) {
Denis Vlasenkofb0eba72008-01-02 19:55:04 +0000294 pid = wait_any_nohang(&wstat);
Denis Vlasenko45946f82007-08-20 17:27:40 +0000295 if (pid <= 0)
296 break;
Denis Vlasenko04c63862006-11-17 18:58:49 +0000297 for (i = 0; i < svnum; i++) {
298 if (pid == sv[i].pid) {
Denis Vlasenko6a2c2cf2008-10-29 12:04:45 +0000299 /* runsv has died */
Denis Vlasenko04c63862006-11-17 18:58:49 +0000300 sv[i].pid = 0;
Denis Vlasenko923a79a2008-09-22 21:34:24 +0000301 need_rescan = 1;
Denis Vlasenko04c63862006-11-17 18:58:49 +0000302 }
303 }
304 }
305
Denis Vlasenko45946f82007-08-20 17:27:40 +0000306 now = monotonic_sec();
307 if ((int)(now - stampcheck) >= 0) {
Denis Vlasenko04c63862006-11-17 18:58:49 +0000308 /* wait at least a second */
Denis Vlasenko45946f82007-08-20 17:27:40 +0000309 stampcheck = now + 1;
Denis Vlasenkof7996f32007-01-11 17:20:00 +0000310
Denis Vlasenko04c63862006-11-17 18:58:49 +0000311 if (stat(svdir, &s) != -1) {
Denis Vlasenko923a79a2008-09-22 21:34:24 +0000312 if (need_rescan || s.st_mtime != last_mtime
Denis Vlasenko45946f82007-08-20 17:27:40 +0000313 || s.st_ino != last_ino || s.st_dev != last_dev
Denis Vlasenko04c63862006-11-17 18:58:49 +0000314 ) {
315 /* svdir modified */
316 if (chdir(svdir) != -1) {
Denis Vlasenko45946f82007-08-20 17:27:40 +0000317 last_mtime = s.st_mtime;
318 last_dev = s.st_dev;
319 last_ino = s.st_ino;
Eric Lammerts31905f92010-12-06 01:26:26 +0100320 /* if the svdir changed this very second, wait until the
321 * next second, because we won't be able to detect more
322 * changes within this second */
323 while (time(NULL) == last_mtime)
324 usleep(100000);
Denis Vlasenko6a2c2cf2008-10-29 12:04:45 +0000325 need_rescan = do_rescan();
Denis Vlasenko04c63862006-11-17 18:58:49 +0000326 while (fchdir(curdir) == -1) {
327 warn2_cannot("change directory, pausing", "");
328 sleep(5);
329 }
Denis Vlasenko6a2c2cf2008-10-29 12:04:45 +0000330 } else {
Denis Vlasenko04c63862006-11-17 18:58:49 +0000331 warn2_cannot("change directory to ", svdir);
Denis Vlasenko6a2c2cf2008-10-29 12:04:45 +0000332 }
Denis Vlasenko04c63862006-11-17 18:58:49 +0000333 }
Denis Vlasenko6a2c2cf2008-10-29 12:04:45 +0000334 } else {
Denis Vlasenko04c63862006-11-17 18:58:49 +0000335 warn2_cannot("stat ", svdir);
Denis Vlasenko6a2c2cf2008-10-29 12:04:45 +0000336 }
Denis Vlasenko04c63862006-11-17 18:58:49 +0000337 }
338
Denis Vlasenko923a79a2008-09-22 21:34:24 +0000339#if ENABLE_FEATURE_RUNSVDIR_LOG
Denis Vlasenko04c63862006-11-17 18:58:49 +0000340 if (rplog) {
Denis Vlasenko45946f82007-08-20 17:27:40 +0000341 if ((int)(now - stamplog) >= 0) {
Denis Vlasenko37188322008-02-16 13:20:56 +0000342 write(logpipe.wr, ".", 1);
Denis Vlasenko45946f82007-08-20 17:27:40 +0000343 stamplog = now + 900;
Denis Vlasenko04c63862006-11-17 18:58:49 +0000344 }
345 }
Denis Vlasenko45946f82007-08-20 17:27:40 +0000346 pfd[0].revents = 0;
Denis Vlasenko923a79a2008-09-22 21:34:24 +0000347#endif
Denis Vlasenko923a79a2008-09-22 21:34:24 +0000348 deadline = (need_rescan ? 1 : 5);
Denis Vlasenko96575962008-10-29 03:42:44 +0000349 sig_block(SIGCHLD);
Denis Vlasenko923a79a2008-09-22 21:34:24 +0000350#if ENABLE_FEATURE_RUNSVDIR_LOG
Denis Vlasenko04c63862006-11-17 18:58:49 +0000351 if (rplog)
Denis Vlasenko45946f82007-08-20 17:27:40 +0000352 poll(pfd, 1, deadline*1000);
Denis Vlasenko04c63862006-11-17 18:58:49 +0000353 else
Denis Vlasenko923a79a2008-09-22 21:34:24 +0000354#endif
Denis Vlasenko45946f82007-08-20 17:27:40 +0000355 sleep(deadline);
Denis Vlasenko8c783952007-01-27 22:21:52 +0000356 sig_unblock(SIGCHLD);
Denis Vlasenko04c63862006-11-17 18:58:49 +0000357
Denis Vlasenko923a79a2008-09-22 21:34:24 +0000358#if ENABLE_FEATURE_RUNSVDIR_LOG
Denis Vlasenko45946f82007-08-20 17:27:40 +0000359 if (pfd[0].revents & POLLIN) {
Denis Vlasenko923a79a2008-09-22 21:34:24 +0000360 char ch;
Denis Vlasenko37188322008-02-16 13:20:56 +0000361 while (read(logpipe.rd, &ch, 1) > 0) {
Denis Vlasenko96575962008-10-29 03:42:44 +0000362 if (ch < ' ')
363 ch = ' ';
364 for (i = 6; i < rploglen; i++)
365 rplog[i-1] = rplog[i];
366 rplog[rploglen-1] = ch;
Denis Vlasenko45946f82007-08-20 17:27:40 +0000367 }
368 }
Denis Vlasenko923a79a2008-09-22 21:34:24 +0000369#endif
Denis Vlasenko3854c5d2008-11-06 22:39:57 +0000370 if (!bb_got_signal)
371 continue;
372
373 /* -s SCRIPT: useful if we are init.
374 * In this case typically script never returns,
375 * it halts/powers off/reboots the system. */
376 if (opt_s_argv[0]) {
377 /* Single parameter: signal# */
378 opt_s_argv[1] = utoa(bb_got_signal);
379 pid = spawn(opt_s_argv);
380 if (pid > 0) {
Denis Vlasenko93b38202009-02-14 20:58:13 +0000381 /* Remembering to wait for _any_ children,
Denis Vlasenko3854c5d2008-11-06 22:39:57 +0000382 * not just pid */
383 while (wait(NULL) != pid)
384 continue;
385 }
386 }
387
Denis Vlasenko3b35fbb2008-11-11 09:33:24 +0000388 if (bb_got_signal == SIGHUP) {
Denis Vlasenko04c63862006-11-17 18:58:49 +0000389 for (i = 0; i < svnum; i++)
390 if (sv[i].pid)
391 kill(sv[i].pid, SIGTERM);
Denis Vlasenko04c63862006-11-17 18:58:49 +0000392 }
Denis Vlasenko3b35fbb2008-11-11 09:33:24 +0000393 /* SIGHUP or SIGTERM (or SIGUSRn if we are init) */
394 /* Exit unless we are init */
395 if (getpid() != 1)
396 return (SIGHUP == bb_got_signal) ? 111 : EXIT_SUCCESS;
Denis Vlasenko3854c5d2008-11-06 22:39:57 +0000397
Denis Vlasenko3b35fbb2008-11-11 09:33:24 +0000398 /* init continues to monitor services forever */
Denis Vlasenko3854c5d2008-11-06 22:39:57 +0000399 bb_got_signal = 0;
400 } /* for (;;) */
Denis Vlasenko04c63862006-11-17 18:58:49 +0000401}