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:
parent
e7368f16fa
commit
6a2c2cf6f3
@ -58,7 +58,6 @@ struct globals {
|
||||
struct pollfd pfd[1];
|
||||
unsigned stamplog;
|
||||
#endif
|
||||
smallint need_rescan; /* = 1; */
|
||||
smallint set_pgrp;
|
||||
};
|
||||
#define G (*(struct globals*)&bb_common_bufsiz1)
|
||||
@ -70,10 +69,8 @@ struct globals {
|
||||
#define logpipe (G.logpipe )
|
||||
#define pfd (G.pfd )
|
||||
#define stamplog (G.stamplog )
|
||||
#define need_rescan (G.need_rescan )
|
||||
#define set_pgrp (G.set_pgrp )
|
||||
#define INIT_G() do { \
|
||||
need_rescan = 1; \
|
||||
} while (0)
|
||||
|
||||
static void fatal2_cannot(const char *m1, const char *m2)
|
||||
@ -96,21 +93,27 @@ static void warnx(const char *m1)
|
||||
}
|
||||
#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) {
|
||||
warn2_cannot("vfork", "");
|
||||
return;
|
||||
return 0;
|
||||
}
|
||||
if (pid == 0) {
|
||||
/* child */
|
||||
if (set_pgrp)
|
||||
setsid();
|
||||
/* man execv:
|
||||
* Signals set to be caught by the calling process image
|
||||
* shall be set to the default action in the new process image.
|
||||
* "Signals set to be caught by the calling process image
|
||||
* shall be set to the default action in the new process image."
|
||||
* Therefore, we do not need this: */
|
||||
#if 0
|
||||
bb_signals(0
|
||||
@ -121,20 +124,22 @@ static void runsv(int no, const char *name)
|
||||
execlp("runsv", "runsv", name, NULL);
|
||||
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;
|
||||
direntry *d;
|
||||
int i;
|
||||
struct stat s;
|
||||
int need_rescan = 0;
|
||||
|
||||
dir = opendir(".");
|
||||
if (!dir) {
|
||||
warn2_cannot("open directory ", svdir);
|
||||
return;
|
||||
return 1; /* need to rescan again soon */
|
||||
}
|
||||
for (i = 0; i < svnum; i++)
|
||||
sv[i].isgone = 1;
|
||||
@ -152,47 +157,47 @@ static void do_rescan(void)
|
||||
}
|
||||
if (!S_ISDIR(s.st_mode))
|
||||
continue;
|
||||
/* Do we have this service listed already? */
|
||||
for (i = 0; i < svnum; i++) {
|
||||
if ((sv[i].ino == s.st_ino)
|
||||
#if CHECK_DEVNO_TOO
|
||||
&& (sv[i].dev == s.st_dev)
|
||||
#endif
|
||||
) {
|
||||
sv[i].isgone = 0;
|
||||
if (!sv[i].pid)
|
||||
runsv(i, d->d_name);
|
||||
break;
|
||||
if (sv[i].pid == 0) /* restart if it has died */
|
||||
goto run_ith_sv;
|
||||
sv[i].isgone = 0; /* "we still see you" */
|
||||
goto next_dentry;
|
||||
}
|
||||
}
|
||||
if (i == svnum) {
|
||||
/* new service */
|
||||
{ /* Not found, make new service */
|
||||
struct service *svnew = realloc(sv, (i+1) * sizeof(*sv));
|
||||
if (!svnew) {
|
||||
warn2_cannot("start runsv ", d->d_name);
|
||||
need_rescan = 1;
|
||||
continue;
|
||||
}
|
||||
sv = svnew;
|
||||
svnum++;
|
||||
memset(&sv[i], 0, sizeof(sv[i]));
|
||||
sv[i].ino = s.st_ino;
|
||||
#if CHECK_DEVNO_TOO
|
||||
sv[i].dev = s.st_dev;
|
||||
#endif
|
||||
/*sv[i].pid = 0;*/
|
||||
/*sv[i].isgone = 0;*/
|
||||
runsv(i, d->d_name);
|
||||
need_rescan = 1;
|
||||
sv[i].ino = s.st_ino;
|
||||
run_ith_sv:
|
||||
sv[i].pid = runsv(d->d_name);
|
||||
sv[i].isgone = 0;
|
||||
}
|
||||
next_dentry: ;
|
||||
}
|
||||
i = errno;
|
||||
closedir(dir);
|
||||
if (i) {
|
||||
if (i) { /* readdir failed */
|
||||
warn2_cannot("read directory ", svdir);
|
||||
need_rescan = 1;
|
||||
return;
|
||||
return 1; /* need to rescan again soon */
|
||||
}
|
||||
|
||||
/* 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++) {
|
||||
if (!sv[i].isgone)
|
||||
continue;
|
||||
@ -201,8 +206,8 @@ static void do_rescan(void)
|
||||
svnum--;
|
||||
sv[i] = sv[svnum];
|
||||
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;
|
||||
@ -219,6 +224,7 @@ int runsvdir_main(int argc UNUSED_PARAM, char **argv)
|
||||
unsigned now;
|
||||
unsigned stampcheck;
|
||||
int i;
|
||||
int need_rescan = 1;
|
||||
|
||||
INIT_G();
|
||||
|
||||
@ -284,10 +290,9 @@ int runsvdir_main(int argc UNUSED_PARAM, char **argv)
|
||||
break;
|
||||
for (i = 0; i < svnum; i++) {
|
||||
if (pid == sv[i].pid) {
|
||||
/* runsv has gone */
|
||||
/* runsv has died */
|
||||
sv[i].pid = 0;
|
||||
need_rescan = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -306,19 +311,20 @@ int runsvdir_main(int argc UNUSED_PARAM, char **argv)
|
||||
last_mtime = s.st_mtime;
|
||||
last_dev = s.st_dev;
|
||||
last_ino = s.st_ino;
|
||||
need_rescan = 0;
|
||||
//if (now <= mtime)
|
||||
// sleep(1);
|
||||
do_rescan();
|
||||
need_rescan = do_rescan();
|
||||
while (fchdir(curdir) == -1) {
|
||||
warn2_cannot("change directory, pausing", "");
|
||||
sleep(5);
|
||||
}
|
||||
} else
|
||||
} else {
|
||||
warn2_cannot("change directory to ", svdir);
|
||||
}
|
||||
}
|
||||
} else
|
||||
} else {
|
||||
warn2_cannot("stat ", svdir);
|
||||
}
|
||||
}
|
||||
|
||||
#if ENABLE_FEATURE_RUNSVDIR_LOG
|
||||
@ -354,6 +360,8 @@ int runsvdir_main(int argc UNUSED_PARAM, char **argv)
|
||||
}
|
||||
#endif
|
||||
switch (bb_got_signal) {
|
||||
case 0: /* we are not signaled, business as usual */
|
||||
break;
|
||||
case SIGHUP:
|
||||
for (i = 0; i < svnum; i++)
|
||||
if (sv[i].pid)
|
||||
|
Loading…
Reference in New Issue
Block a user