runsvdir: conditionalize "log in argiment" (mis)feature. By Vladimir. with: runsv 139 141 +2 runsvdir_main 1583 1513 -70
No binary (build failed)
—
(log yok)
| @@ -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 | |
| @@ -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++) | |