diff options
-rw-r--r-- | runit/Config.in | 9 | ||||
-rw-r--r-- | runit/runsvdir.c | 143 |
2 files changed, 88 insertions, 64 deletions
diff --git a/runit/Config.in b/runit/Config.in index 8a7deea72..beff1e7e2 100644 --- a/runit/Config.in +++ b/runit/Config.in @@ -20,6 +20,15 @@ config RUNSVDIR a directory, in the services directory dir, up to a limit of 1000 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 bool "sv" default n diff --git a/runit/runsvdir.c b/runit/runsvdir.c index 0dedd5c77..8099ebf5c 100644 --- a/runit/runsvdir.c +++ b/runit/runsvdir.c @@ -35,8 +35,13 @@ ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #define MAXSERVICES 1000 +/* Should be not needed - all dirs are on same FS, right? */ +#define CHECK_DEVNO_TOO 0 + struct service { +#if CHECK_DEVNO_TOO dev_t dev; +#endif ino_t ino; pid_t pid; smallint isgone; @@ -45,28 +50,30 @@ struct service { struct globals { struct service *sv; char *svdir; - char *rplog; int svnum; +#if ENABLE_FEATURE_RUNSVDIR_LOG + char *rplog; int rploglen; struct fd_pair logpipe; struct pollfd pfd[1]; unsigned stamplog; - smallint check; /* = 1; */ +#endif + smallint need_rescan; /* = 1; */ smallint set_pgrp; }; #define G (*(struct globals*)&bb_common_bufsiz1) -#define sv (G.sv ) -#define svdir (G.svdir ) -#define rplog (G.rplog ) -#define svnum (G.svnum ) -#define rploglen (G.rploglen ) -#define logpipe (G.logpipe ) -#define pfd (G.pfd ) -#define stamplog (G.stamplog ) -#define check (G.check ) -#define set_pgrp (G.set_pgrp ) +#define sv (G.sv ) +#define svdir (G.svdir ) +#define svnum (G.svnum ) +#define rplog (G.rplog ) +#define rploglen (G.rploglen ) +#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 { \ - check = 1; \ + need_rescan = 1; \ } while (0) 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); } +#if ENABLE_FEATURE_RUNSVDIR_LOG static void warnx(const char *m1) { warn3x(m1, "", ""); } +#endif static void runsv(int no, const char *name) { @@ -116,7 +125,7 @@ static void runsv(int no, const char *name) sv[no].pid = pid; } -static void runsvdir(void) +static void do_rescan(void) { DIR *dir; direntry *d; @@ -140,13 +149,16 @@ static void runsvdir(void) continue; if (stat(d->d_name, &s) == -1) { warn2_cannot("stat ", d->d_name); - errno = 0; continue; } if (!S_ISDIR(s.st_mode)) continue; 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; if (!sv[i].pid) runsv(i, d->d_name); @@ -157,66 +169,43 @@ static void runsvdir(void) /* new service */ struct service *svnew = realloc(sv, (i+1) * sizeof(*sv)); if (!svnew) { - warn3x("cannot start runsv ", d->d_name, - " too many services"); + warn2_cannot("start runsv ", d->d_name); 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); - check = 1; + need_rescan = 1; } } - if (errno) { + i = errno; + closedir(dir); + if (i) { warn2_cannot("read directory ", svdir); - closedir(dir); - check = 1; + need_rescan = 1; return; } - closedir(dir); - /* SIGTERM removed runsv's */ + /* Send SIGTERM to runsv whose directories were not found (removed) */ for (i = 0; i < svnum; i++) { if (!sv[i].isgone) continue; if (sv[i].pid) kill(sv[i].pid, SIGTERM); - sv[i] = sv[--svnum]; -/* BUG? we deleted sv[i] by copying over sv[last], but we will not check this newly-copied one! */ - check = 1; + svnum--; + sv[i] = sv[svnum]; + 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 UNUSED_PARAM, char **argv) { @@ -230,7 +219,6 @@ int runsvdir_main(int argc UNUSED_PARAM, char **argv) unsigned deadline; unsigned now; unsigned stampcheck; - char ch; int i; INIT_G(); @@ -241,13 +229,35 @@ int runsvdir_main(int argc UNUSED_PARAM, char **argv) bb_signals_recursive((1 << SIGTERM) | (1 << SIGHUP), record_signo); svdir = *argv++; - if (argv && *argv) { + +#if ENABLE_FEATURE_RUNSVDIR_LOG + /* setup log */ + if (*argv) { rplog = *argv; - if (setup_log() != 1) { - rplog = 0; - warnx("log service disabled"); + rploglen = strlen(rplog); + if (rploglen < 7) { + 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("."); if (curdir == -1) fatal2_cannot("open current directory", ""); @@ -265,7 +275,7 @@ int runsvdir_main(int argc UNUSED_PARAM, char **argv) if (pid == sv[i].pid) { /* runsv has gone */ sv[i].pid = 0; - check = 1; + need_rescan = 1; break; } } @@ -277,7 +287,7 @@ int runsvdir_main(int argc UNUSED_PARAM, char **argv) stampcheck = now + 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 ) { /* svdir modified */ @@ -285,10 +295,10 @@ int runsvdir_main(int argc UNUSED_PARAM, char **argv) last_mtime = s.st_mtime; last_dev = s.st_dev; last_ino = s.st_ino; - check = 0; + need_rescan = 0; //if (now <= mtime) // sleep(1); - runsvdir(); + do_rescan(); while (fchdir(curdir) == -1) { warn2_cannot("change directory, pausing", ""); sleep(5); @@ -300,23 +310,28 @@ int runsvdir_main(int argc UNUSED_PARAM, char **argv) warn2_cannot("stat ", svdir); } +#if ENABLE_FEATURE_RUNSVDIR_LOG if (rplog) { if ((int)(now - stamplog) >= 0) { write(logpipe.wr, ".", 1); stamplog = now + 900; } } - pfd[0].revents = 0; +#endif sig_block(SIGCHLD); - deadline = (check ? 1 : 5); + deadline = (need_rescan ? 1 : 5); +#if ENABLE_FEATURE_RUNSVDIR_LOG if (rplog) poll(pfd, 1, deadline*1000); else +#endif sleep(deadline); sig_unblock(SIGCHLD); +#if ENABLE_FEATURE_RUNSVDIR_LOG if (pfd[0].revents & POLLIN) { + char ch; while (read(logpipe.rd, &ch, 1) > 0) { if (ch) { for (i = 6; i < rploglen; i++) @@ -325,7 +340,7 @@ int runsvdir_main(int argc UNUSED_PARAM, char **argv) } } } - +#endif switch (bb_got_signal) { case SIGHUP: for (i = 0; i < svnum; i++) |