runsvdir: conditionalize "log in argiment" (mis)feature. By Vladimir.

with:
runsv                                                139     141      +2
runsvdir_main                                       1583    1513     -70

 without:
warn2_cannot                                          14      27     +13
runsv                                                139     141      +2
warnx                                                 28      16     -12
warn3x                                                23       -     -23
runsvdir_main                                       1583    1125    -458
This commit is contained in:
Denis Vlasenko 2008-09-22 21:34:24 +00:00
parent 30cfdf90ce
commit 923a79a769
2 changed files with 88 additions and 64 deletions

View File

@ -20,6 +20,15 @@ config RUNSVDIR
a directory, in the services directory dir, up to a limit of 1000 a directory, in the services directory dir, up to a limit of 1000
subdirectories, and restarts a runsv process if it terminates. subdirectories, and restarts a runsv process if it terminates.
config FEATURE_RUNSVDIR_LOG
bool "Enable scrolling argument log"
depends on RUNSVDIR
default n
help
Enable feature where second parameter of runsvdir holds last error
message (viewable via top/ps). Otherwise (feature is off
or no parameter), error messages go to stderr only.
config SV config SV
bool "sv" bool "sv"
default n default n

View File

@ -35,8 +35,13 @@ ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#define MAXSERVICES 1000 #define MAXSERVICES 1000
/* Should be not needed - all dirs are on same FS, right? */
#define CHECK_DEVNO_TOO 0
struct service { struct service {
#if CHECK_DEVNO_TOO
dev_t dev; dev_t dev;
#endif
ino_t ino; ino_t ino;
pid_t pid; pid_t pid;
smallint isgone; smallint isgone;
@ -45,28 +50,30 @@ struct service {
struct globals { struct globals {
struct service *sv; struct service *sv;
char *svdir; char *svdir;
char *rplog;
int svnum; int svnum;
#if ENABLE_FEATURE_RUNSVDIR_LOG
char *rplog;
int rploglen; int rploglen;
struct fd_pair logpipe; struct fd_pair logpipe;
struct pollfd pfd[1]; struct pollfd pfd[1];
unsigned stamplog; unsigned stamplog;
smallint check; /* = 1; */ #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)
#define sv (G.sv ) #define sv (G.sv )
#define svdir (G.svdir ) #define svdir (G.svdir )
#define rplog (G.rplog ) #define svnum (G.svnum )
#define svnum (G.svnum ) #define rplog (G.rplog )
#define rploglen (G.rploglen ) #define rploglen (G.rploglen )
#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 check (G.check ) #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 { \
check = 1; \ 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)
@ -82,10 +89,12 @@ static void warn2_cannot(const char *m1, const char *m2)
{ {
warn3x("cannot ", m1, m2); warn3x("cannot ", m1, m2);
} }
#if ENABLE_FEATURE_RUNSVDIR_LOG
static void warnx(const char *m1) static void warnx(const char *m1)
{ {
warn3x(m1, "", ""); warn3x(m1, "", "");
} }
#endif
static void runsv(int no, const char *name) static void runsv(int no, const char *name)
{ {
@ -116,7 +125,7 @@ static void runsv(int no, const char *name)
sv[no].pid = pid; sv[no].pid = pid;
} }
static void runsvdir(void) static void do_rescan(void)
{ {
DIR *dir; DIR *dir;
direntry *d; direntry *d;
@ -140,13 +149,16 @@ static void runsvdir(void)
continue; continue;
if (stat(d->d_name, &s) == -1) { if (stat(d->d_name, &s) == -1) {
warn2_cannot("stat ", d->d_name); warn2_cannot("stat ", d->d_name);
errno = 0;
continue; continue;
} }
if (!S_ISDIR(s.st_mode)) if (!S_ISDIR(s.st_mode))
continue; continue;
for (i = 0; i < svnum; i++) { for (i = 0; i < svnum; i++) {
if ((sv[i].ino == s.st_ino) && (sv[i].dev == s.st_dev)) { if ((sv[i].ino == s.st_ino)
#if CHECK_DEVNO_TOO
&& (sv[i].dev == s.st_dev)
#endif
) {
sv[i].isgone = 0; sv[i].isgone = 0;
if (!sv[i].pid) if (!sv[i].pid)
runsv(i, d->d_name); runsv(i, d->d_name);
@ -157,66 +169,43 @@ static void runsvdir(void)
/* 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) {
warn3x("cannot start runsv ", d->d_name, warn2_cannot("start runsv ", d->d_name);
" too many services");
continue; continue;
} }
sv = svnew; sv = svnew;
svnum++; svnum++;
memset(&sv[i], 0, sizeof(sv[i])); memset(&sv[i], 0, sizeof(sv[i]));
sv[i].ino = s.st_ino; sv[i].ino = s.st_ino;
#if CHECK_DEVNO_TOO
sv[i].dev = s.st_dev; sv[i].dev = s.st_dev;
#endif
/*sv[i].pid = 0;*/ /*sv[i].pid = 0;*/
/*sv[i].isgone = 0;*/ /*sv[i].isgone = 0;*/
runsv(i, d->d_name); runsv(i, d->d_name);
check = 1; need_rescan = 1;
} }
} }
if (errno) { i = errno;
closedir(dir);
if (i) {
warn2_cannot("read directory ", svdir); warn2_cannot("read directory ", svdir);
closedir(dir); need_rescan = 1;
check = 1;
return; return;
} }
closedir(dir);
/* SIGTERM removed runsv's */ /* Send SIGTERM to runsv whose directories were not found (removed) */
for (i = 0; i < svnum; i++) { for (i = 0; i < svnum; i++) {
if (!sv[i].isgone) if (!sv[i].isgone)
continue; continue;
if (sv[i].pid) if (sv[i].pid)
kill(sv[i].pid, SIGTERM); kill(sv[i].pid, SIGTERM);
sv[i] = sv[--svnum]; svnum--;
/* BUG? we deleted sv[i] by copying over sv[last], but we will not check this newly-copied one! */ sv[i] = sv[svnum];
check = 1; i--; /* so that we don't skip new sv[i] (bug was here!) */
need_rescan = 1;
} }
} }
static int setup_log(void)
{
rploglen = strlen(rplog);
if (rploglen < 7) {
warnx("log must have at least seven characters");
return 0;
}
if (piped_pair(logpipe)) {
warnx("cannot create pipe for log");
return -1;
}
close_on_exec_on(logpipe.rd);
close_on_exec_on(logpipe.wr);
ndelay_on(logpipe.rd);
ndelay_on(logpipe.wr);
if (dup2(logpipe.wr, 2) == -1) {
warnx("cannot set filedescriptor for log");
return -1;
}
pfd[0].fd = logpipe.rd;
pfd[0].events = POLLIN;
stamplog = monotonic_sec();
return 1;
}
int runsvdir_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; int runsvdir_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
int runsvdir_main(int argc UNUSED_PARAM, char **argv) int runsvdir_main(int argc UNUSED_PARAM, char **argv)
{ {
@ -230,7 +219,6 @@ int runsvdir_main(int argc UNUSED_PARAM, char **argv)
unsigned deadline; unsigned deadline;
unsigned now; unsigned now;
unsigned stampcheck; unsigned stampcheck;
char ch;
int i; int i;
INIT_G(); INIT_G();
@ -241,13 +229,35 @@ int runsvdir_main(int argc UNUSED_PARAM, char **argv)
bb_signals_recursive((1 << SIGTERM) | (1 << SIGHUP), record_signo); bb_signals_recursive((1 << SIGTERM) | (1 << SIGHUP), record_signo);
svdir = *argv++; svdir = *argv++;
if (argv && *argv) {
#if ENABLE_FEATURE_RUNSVDIR_LOG
/* setup log */
if (*argv) {
rplog = *argv; rplog = *argv;
if (setup_log() != 1) { rploglen = strlen(rplog);
rplog = 0; if (rploglen < 7) {
warnx("log service disabled"); warnx("log must have at least seven characters");
} else if (piped_pair(logpipe)) {
warnx("cannot create pipe for log");
} else {
close_on_exec_on(logpipe.rd);
close_on_exec_on(logpipe.wr);
ndelay_on(logpipe.rd);
ndelay_on(logpipe.wr);
if (dup2(logpipe.wr, 2) == -1) {
warnx("cannot set filedescriptor for log");
} else {
pfd[0].fd = logpipe.rd;
pfd[0].events = POLLIN;
stamplog = monotonic_sec();
goto run;
}
} }
rplog = NULL;
warnx("log service disabled");
} }
run:
#endif
curdir = open_read("."); curdir = open_read(".");
if (curdir == -1) if (curdir == -1)
fatal2_cannot("open current directory", ""); fatal2_cannot("open current directory", "");
@ -265,7 +275,7 @@ int runsvdir_main(int argc UNUSED_PARAM, char **argv)
if (pid == sv[i].pid) { if (pid == sv[i].pid) {
/* runsv has gone */ /* runsv has gone */
sv[i].pid = 0; sv[i].pid = 0;
check = 1; need_rescan = 1;
break; break;
} }
} }
@ -277,7 +287,7 @@ int runsvdir_main(int argc UNUSED_PARAM, char **argv)
stampcheck = now + 1; stampcheck = now + 1;
if (stat(svdir, &s) != -1) { if (stat(svdir, &s) != -1) {
if (check || s.st_mtime != last_mtime if (need_rescan || s.st_mtime != last_mtime
|| s.st_ino != last_ino || s.st_dev != last_dev || s.st_ino != last_ino || s.st_dev != last_dev
) { ) {
/* svdir modified */ /* svdir modified */
@ -285,10 +295,10 @@ 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;
check = 0; need_rescan = 0;
//if (now <= mtime) //if (now <= mtime)
// sleep(1); // sleep(1);
runsvdir(); do_rescan();
while (fchdir(curdir) == -1) { while (fchdir(curdir) == -1) {
warn2_cannot("change directory, pausing", ""); warn2_cannot("change directory, pausing", "");
sleep(5); sleep(5);
@ -300,23 +310,28 @@ int runsvdir_main(int argc UNUSED_PARAM, char **argv)
warn2_cannot("stat ", svdir); warn2_cannot("stat ", svdir);
} }
#if ENABLE_FEATURE_RUNSVDIR_LOG
if (rplog) { if (rplog) {
if ((int)(now - stamplog) >= 0) { if ((int)(now - stamplog) >= 0) {
write(logpipe.wr, ".", 1); write(logpipe.wr, ".", 1);
stamplog = now + 900; stamplog = now + 900;
} }
} }
pfd[0].revents = 0; pfd[0].revents = 0;
#endif
sig_block(SIGCHLD); sig_block(SIGCHLD);
deadline = (check ? 1 : 5); deadline = (need_rescan ? 1 : 5);
#if ENABLE_FEATURE_RUNSVDIR_LOG
if (rplog) if (rplog)
poll(pfd, 1, deadline*1000); poll(pfd, 1, deadline*1000);
else else
#endif
sleep(deadline); sleep(deadline);
sig_unblock(SIGCHLD); sig_unblock(SIGCHLD);
#if ENABLE_FEATURE_RUNSVDIR_LOG
if (pfd[0].revents & POLLIN) { if (pfd[0].revents & POLLIN) {
char ch;
while (read(logpipe.rd, &ch, 1) > 0) { while (read(logpipe.rd, &ch, 1) > 0) {
if (ch) { if (ch) {
for (i = 6; i < rploglen; i++) for (i = 6; i < rploglen; i++)
@ -325,7 +340,7 @@ int runsvdir_main(int argc UNUSED_PARAM, char **argv)
} }
} }
} }
#endif
switch (bb_got_signal) { switch (bb_got_signal) {
case SIGHUP: case SIGHUP:
for (i = 0; i < svnum; i++) for (i = 0; i < svnum; i++)