runsvdir: conditionalize "log in argiment" (mis)feature. By Vladimir.
authorDenis Vlasenko <vda.linux@googlemail.com>
Mon, 22 Sep 2008 21:34:24 +0000 (21:34 -0000)
committerDenis Vlasenko <vda.linux@googlemail.com>
Mon, 22 Sep 2008 21:34:24 +0000 (21:34 -0000)
 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

runit/Config.in
runit/runsvdir.c

index 8a7deea..beff1e7 100644 (file)
@@ -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
index 0dedd5c..8099ebf 100644 (file)
@@ -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++)