runsvdir: fx a recent vda's buglet (was pausing even if not signaled).

stop spawning children immediately if signaled. Kill one global.
This commit is contained in:
Denis Vlasenko 2008-10-29 12:04:45 +00:00
parent e7368f16fa
commit 6a2c2cf6f3

View File

@ -58,7 +58,6 @@ struct globals {
struct pollfd pfd[1]; struct pollfd pfd[1];
unsigned stamplog; unsigned stamplog;
#endif #endif
smallint need_rescan; /* = 1; */
smallint set_pgrp; smallint set_pgrp;
}; };
#define G (*(struct globals*)&bb_common_bufsiz1) #define G (*(struct globals*)&bb_common_bufsiz1)
@ -70,10 +69,8 @@ struct globals {
#define logpipe (G.logpipe ) #define logpipe (G.logpipe )
#define pfd (G.pfd ) #define pfd (G.pfd )
#define stamplog (G.stamplog ) #define stamplog (G.stamplog )
#define need_rescan (G.need_rescan )
#define set_pgrp (G.set_pgrp ) #define set_pgrp (G.set_pgrp )
#define INIT_G() do { \ #define INIT_G() do { \
need_rescan = 1; \
} while (0) } while (0)
static void fatal2_cannot(const char *m1, const char *m2) static void fatal2_cannot(const char *m1, const char *m2)
@ -96,21 +93,27 @@ static void warnx(const char *m1)
} }
#endif #endif
static void runsv(int no, const char *name) /* inlining + vfork -> bigger code */
static NOINLINE pid_t runsv(const char *name)
{ {
pid_t pid = vfork(); pid_t pid;
/* If we got signaled, stop spawning children at once! */
if (bb_got_signal)
return 0;
pid = vfork();
if (pid == -1) { if (pid == -1) {
warn2_cannot("vfork", ""); warn2_cannot("vfork", "");
return; return 0;
} }
if (pid == 0) { if (pid == 0) {
/* child */ /* child */
if (set_pgrp) if (set_pgrp)
setsid(); setsid();
/* man execv: /* man execv:
* Signals set to be caught by the calling process image * "Signals set to be caught by the calling process image
* shall be set to the default action in the new process image. * shall be set to the default action in the new process image."
* Therefore, we do not need this: */ * Therefore, we do not need this: */
#if 0 #if 0
bb_signals(0 bb_signals(0
@ -121,20 +124,22 @@ static void runsv(int no, const char *name)
execlp("runsv", "runsv", name, NULL); execlp("runsv", "runsv", name, NULL);
fatal2_cannot("start runsv ", name); fatal2_cannot("start runsv ", name);
} }
sv[no].pid = pid; return pid;
} }
static void do_rescan(void) /* gcc 4.3.0 does better with NOINLINE */
static NOINLINE int do_rescan(void)
{ {
DIR *dir; DIR *dir;
direntry *d; direntry *d;
int i; int i;
struct stat s; struct stat s;
int need_rescan = 0;
dir = opendir("."); dir = opendir(".");
if (!dir) { if (!dir) {
warn2_cannot("open directory ", svdir); warn2_cannot("open directory ", svdir);
return; return 1; /* need to rescan again soon */
} }
for (i = 0; i < svnum; i++) for (i = 0; i < svnum; i++)
sv[i].isgone = 1; sv[i].isgone = 1;
@ -152,47 +157,47 @@ static void do_rescan(void)
} }
if (!S_ISDIR(s.st_mode)) if (!S_ISDIR(s.st_mode))
continue; continue;
/* Do we have this service listed already? */
for (i = 0; i < svnum; i++) { for (i = 0; i < svnum; i++) {
if ((sv[i].ino == s.st_ino) if ((sv[i].ino == s.st_ino)
#if CHECK_DEVNO_TOO #if CHECK_DEVNO_TOO
&& (sv[i].dev == s.st_dev) && (sv[i].dev == s.st_dev)
#endif #endif
) { ) {
sv[i].isgone = 0; if (sv[i].pid == 0) /* restart if it has died */
if (!sv[i].pid) goto run_ith_sv;
runsv(i, d->d_name); sv[i].isgone = 0; /* "we still see you" */
break; goto next_dentry;
} }
} }
if (i == svnum) { { /* Not found, make new service */
/* new service */
struct service *svnew = realloc(sv, (i+1) * sizeof(*sv)); struct service *svnew = realloc(sv, (i+1) * sizeof(*sv));
if (!svnew) { if (!svnew) {
warn2_cannot("start runsv ", d->d_name); warn2_cannot("start runsv ", d->d_name);
need_rescan = 1;
continue; continue;
} }
sv = svnew; sv = svnew;
svnum++; svnum++;
memset(&sv[i], 0, sizeof(sv[i]));
sv[i].ino = s.st_ino;
#if CHECK_DEVNO_TOO #if CHECK_DEVNO_TOO
sv[i].dev = s.st_dev; sv[i].dev = s.st_dev;
#endif #endif
/*sv[i].pid = 0;*/ sv[i].ino = s.st_ino;
/*sv[i].isgone = 0;*/ run_ith_sv:
runsv(i, d->d_name); sv[i].pid = runsv(d->d_name);
need_rescan = 1; sv[i].isgone = 0;
} }
next_dentry: ;
} }
i = errno; i = errno;
closedir(dir); closedir(dir);
if (i) { if (i) { /* readdir failed */
warn2_cannot("read directory ", svdir); warn2_cannot("read directory ", svdir);
need_rescan = 1; return 1; /* need to rescan again soon */
return;
} }
/* Send SIGTERM to runsv whose directories were not found (removed) */ /* Send SIGTERM to runsv whose directories
* were no longer found (-> must have been removed) */
for (i = 0; i < svnum; i++) { for (i = 0; i < svnum; i++) {
if (!sv[i].isgone) if (!sv[i].isgone)
continue; continue;
@ -201,8 +206,8 @@ static void do_rescan(void)
svnum--; svnum--;
sv[i] = sv[svnum]; sv[i] = sv[svnum];
i--; /* so that we don't skip new sv[i] (bug was here!) */ i--; /* so that we don't skip new sv[i] (bug was here!) */
need_rescan = 1;
} }
return need_rescan;
} }
int runsvdir_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; int runsvdir_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
@ -219,6 +224,7 @@ int runsvdir_main(int argc UNUSED_PARAM, char **argv)
unsigned now; unsigned now;
unsigned stampcheck; unsigned stampcheck;
int i; int i;
int need_rescan = 1;
INIT_G(); INIT_G();
@ -284,10 +290,9 @@ int runsvdir_main(int argc UNUSED_PARAM, char **argv)
break; break;
for (i = 0; i < svnum; i++) { for (i = 0; i < svnum; i++) {
if (pid == sv[i].pid) { if (pid == sv[i].pid) {
/* runsv has gone */ /* runsv has died */
sv[i].pid = 0; sv[i].pid = 0;
need_rescan = 1; need_rescan = 1;
break;
} }
} }
} }
@ -306,19 +311,20 @@ int runsvdir_main(int argc UNUSED_PARAM, char **argv)
last_mtime = s.st_mtime; last_mtime = s.st_mtime;
last_dev = s.st_dev; last_dev = s.st_dev;
last_ino = s.st_ino; last_ino = s.st_ino;
need_rescan = 0;
//if (now <= mtime) //if (now <= mtime)
// sleep(1); // sleep(1);
do_rescan(); need_rescan = do_rescan();
while (fchdir(curdir) == -1) { while (fchdir(curdir) == -1) {
warn2_cannot("change directory, pausing", ""); warn2_cannot("change directory, pausing", "");
sleep(5); sleep(5);
} }
} else } else {
warn2_cannot("change directory to ", svdir); warn2_cannot("change directory to ", svdir);
}
} }
} else } else {
warn2_cannot("stat ", svdir); warn2_cannot("stat ", svdir);
}
} }
#if ENABLE_FEATURE_RUNSVDIR_LOG #if ENABLE_FEATURE_RUNSVDIR_LOG
@ -354,6 +360,8 @@ int runsvdir_main(int argc UNUSED_PARAM, char **argv)
} }
#endif #endif
switch (bb_got_signal) { switch (bb_got_signal) {
case 0: /* we are not signaled, business as usual */
break;
case SIGHUP: case SIGHUP:
for (i = 0; i < svnum; i++) for (i = 0; i < svnum; i++)
if (sv[i].pid) if (sv[i].pid)