X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=runit%2Frunsvdir.c;h=8099ebf5c9090c5492aa287161f4528ca173a2e5;hb=176d49d4f7bd1c049211c704018b1ac9d432f52e;hp=df6b8869da6f79952028ae76fca291f0805c87b7;hpb=8f74094548a1147ed7b459ca771343483b1c202c;p=oweals%2Fbusybox.git diff --git a/runit/runsvdir.c b/runit/runsvdir.c index df6b8869d..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,30 +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; */ - smallint exitsoon; +#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 exitsoon (G.exitsoon ) -#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) @@ -84,19 +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, "", ""); } - -static void s_term(int sig_no ATTRIBUTE_UNUSED) -{ - exitsoon = 1; -} -static void s_hangup(int sig_no ATTRIBUTE_UNUSED) -{ - exitsoon = 2; -} +#endif static void runsv(int no, const char *name) { @@ -127,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; @@ -151,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); @@ -168,68 +169,45 @@ 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; - } -} - -static int setup_log(void) -{ - rploglen = strlen(rplog); - if (rploglen < 7) { - warnx("log must have at least seven characters"); - return 0; + svnum--; + sv[i] = sv[svnum]; + i--; /* so that we don't skip new sv[i] (bug was here!) */ + need_rescan = 1; } - 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 ATTRIBUTE_UNUSED, char **argv) +int runsvdir_main(int argc UNUSED_PARAM, char **argv) { struct stat s; dev_t last_dev = last_dev; /* for gcc */ @@ -241,33 +219,45 @@ int runsvdir_main(int argc ATTRIBUTE_UNUSED, char **argv) unsigned deadline; unsigned now; unsigned stampcheck; - char ch; int i; INIT_G(); - argv++; - if (!*argv) - bb_show_usage(); - if (argv[0][0] == '-') { - switch (argv[0][1]) { - case 'P': set_pgrp = 1; - case '-': ++argv; - } - if (!*argv) - bb_show_usage(); - } + opt_complementary = "-1"; + set_pgrp = getopt32(argv, "P"); + argv += optind; - bb_signals_recursive(1 << SIGTERM, s_term); - bb_signals_recursive(1 << SIGHUP, s_hangup); + 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", ""); @@ -285,7 +275,7 @@ int runsvdir_main(int argc ATTRIBUTE_UNUSED, char **argv) if (pid == sv[i].pid) { /* runsv has gone */ sv[i].pid = 0; - check = 1; + need_rescan = 1; break; } } @@ -297,7 +287,7 @@ int runsvdir_main(int argc ATTRIBUTE_UNUSED, 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 */ @@ -305,10 +295,10 @@ int runsvdir_main(int argc ATTRIBUTE_UNUSED, 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); @@ -320,23 +310,28 @@ int runsvdir_main(int argc ATTRIBUTE_UNUSED, 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++) @@ -345,15 +340,15 @@ int runsvdir_main(int argc ATTRIBUTE_UNUSED, char **argv) } } } - - switch (exitsoon) { - case 1: - _exit(EXIT_SUCCESS); - case 2: +#endif + switch (bb_got_signal) { + case SIGHUP: for (i = 0; i < svnum; i++) if (sv[i].pid) kill(sv[i].pid, SIGTERM); - _exit(111); + // N.B. fall through + case SIGTERM: + _exit((SIGHUP == bb_got_signal) ? 111 : EXIT_SUCCESS); } } /* not reached */