fakeidentd: fix daemon mode (was thinking that it is in
authorDenis Vlasenko <vda.linux@googlemail.com>
Sun, 14 Jan 2007 12:07:25 +0000 (12:07 -0000)
committerDenis Vlasenko <vda.linux@googlemail.com>
Sun, 14 Jan 2007 12:07:25 +0000 (12:07 -0000)
inetd-wait mode and dying after timeout). Minor fixes,
comments are improved in places.

networking/isrv.c
networking/isrv_identd.c

index 02ca1d787f65c0874f54296a852a01d161f16f54..5193f30f33a8a8665bf388cdadfcefa5754ff7e1 100644 (file)
@@ -21,6 +21,8 @@
 
 /* Helpers */
 
+/* Even if _POSIX_MONOTONIC_CLOCK is defined, this
+ * may require librt */
 #if 0 /*def _POSIX_MONOTONIC_CLOCK*/
 static time_t monotonic_time(void)
 {
@@ -194,7 +196,8 @@ static void handle_accept(isrv_state_t *state, int fd)
        if (newfd < 0) {
                if (errno == EAGAIN) return;
                /* Most probably someone gave us wrong fd type
-                * (for example, non-socket) */
+                * (for example, non-socket). Don't want
+                * to loop forever. */
                bb_perror_msg_and_die("accept");
        }
 
@@ -210,6 +213,7 @@ static void handle_fd_set(isrv_state_t *state, fd_set *fds, int (*h)(int, void *
        enum { LONG_CNT = sizeof(fd_set) / sizeof(long) };
        int fds_pos;
        int fd, peer;
+       /* need to know value at _the beginning_ of this routine */
        int fd_cnt = FD_COUNT;
 
        if (LONG_CNT * sizeof(long) != sizeof(fd_set))
@@ -235,10 +239,15 @@ static void handle_fd_set(isrv_state_t *state, fd_set *fds, int (*h)(int, void *
                }
                break; /* all words are zero */
  found_fd:
-               if (fd >= fd_cnt) /* paranoia */
+               if (fd >= fd_cnt) { /* paranoia */
+                       DPRINTF("handle_fd_set: fd > fd_cnt?? (%d > %d)",
+                                       fd, fd_cnt);
                        break;
+               }
                DPRINTF("handle_fd_set: fd %d is active", fd);
                peer = FD2PEER[fd];
+               if (peer < 0)
+                       continue; /* peer is already gone */
                if (peer == 0) {
                        handle_accept(state, fd);
                        continue;
@@ -259,9 +268,9 @@ static void handle_timeout(isrv_state_t *state, int (*do_timeout)(void **))
        peer = PEER_COUNT-1;
        /* peer 0 is not checked */
        while (peer > 0) {
-               DPRINTF("peer %d: time diff %d", peer, (int)(CURTIME - TIMEO_TBL[peer]));
-
-               if ((CURTIME - TIMEO_TBL[peer]) > TIMEOUT) {
+               DPRINTF("peer %d: time diff %d", peer,
+                               (int)(CURTIME - TIMEO_TBL[peer]));
+               if ((CURTIME - TIMEO_TBL[peer]) >= TIMEOUT) {
                        DPRINTF("peer %d: do_timeout()", peer);
                        n = do_timeout(&PARAM_TBL[peer]);
                        if (n)
@@ -279,7 +288,7 @@ void isrv_run(
        int (*do_wr)(int fd, void **),
        int (*do_timeout)(void **),
        int timeout,
-       int exit_if_no_clients)
+       int linger_timeout)
 {
        isrv_state_t *state = xzalloc(sizeof(*state));
        state->new_peer = new_peer;
@@ -300,6 +309,8 @@ void isrv_run(
                int n;
 
                tv.tv_sec = timeout;
+               if (PEER_COUNT <= 1)
+                       tv.tv_sec = linger_timeout;
                tv.tv_usec = 0;
                rd = state->rd;
                if (WR_COUNT) {
@@ -307,8 +318,9 @@ void isrv_run(
                        wrp = &wr;
                }
 
-               DPRINTF("run: select(FD_COUNT:%d,timeout:%d)...", FD_COUNT, timeout);
-               n = select(FD_COUNT, &rd, wrp, NULL, timeout ? &tv : NULL);
+               DPRINTF("run: select(FD_COUNT:%d,timeout:%d)...",
+                               FD_COUNT, (int)tv.tv_sec);
+               n = select(FD_COUNT, &rd, wrp, NULL, tv.tv_sec ? &tv : NULL);
                DPRINTF("run: ...select:%d", n);
 
                if (n < 0) {
@@ -317,7 +329,7 @@ void isrv_run(
                        continue;
                }
 
-               if (exit_if_no_clients && n == 0 && PEER_COUNT <= 1)
+               if (n == 0 && linger_timeout && PEER_COUNT <= 1)
                        break;
 
                if (timeout) {
@@ -334,4 +346,5 @@ void isrv_run(
                }
        }
        DPRINTF("run: bailout");
+       /* NB: accept socket is not closed. Caller is to decide what to do */
 }
index b9481f8d3ea6c2d184acc07efb6587e63c4bdf2f..30f9a7a26344e07bb0f6f976e214d49ff5d9158a 100644 (file)
 
 enum { TIMEOUT = 20 };
 
-/* Why use alarm(TIMEOUT-1)?
- * isrv's internal select() will run with timeout=TIMEOUT.
- * If nothing happens during TIMEOUT-1 seconds (no accept/read),
- * then ALL sessions timed out by now. Instead of closing them one-by-one
- * (isrv calls do_timeout for each 'stale' session),
- * SIGALRM triggered by alarm(TIMEOUT-1) will kill us, terminating them all.
- */
-
 typedef struct identd_buf_t {
        int pos;
        int fd_flag;
@@ -34,8 +26,6 @@ static int new_peer(isrv_state_t *state, int fd)
        int peer;
        identd_buf_t *buf = xzalloc(sizeof(*buf));
 
-       alarm(TIMEOUT - 1);
-
        peer = isrv_register_peer(state, buf);
        if (peer < 0)
                return 0; /* failure */
@@ -53,11 +43,9 @@ static int do_rd(int fd, void **paramp)
        char *cur, *p;
        int sz;
 
-       alarm(TIMEOUT - 1);
-
        cur = buf->buf + buf->pos;
 
-       fcntl(fd, F_SETFL, buf->fd_flag | O_NONBLOCK);
+       fcntl(fd, F_SETFL, buf->fd_flag);
        sz = safe_read(fd, cur, sizeof(buf->buf) - buf->pos);
 
        if (sz < 0) {
@@ -95,6 +83,8 @@ static void inetd_mode(void)
        identd_buf_t *buf = xzalloc(sizeof(*buf));
        /* We do NOT want nonblocking I/O here! */
        buf->fd_flag = fcntl(0, F_GETFL, 0);
+       do
+               alarm(TIMEOUT);
        while (do_rd(0, (void*)&buf) == 0) /* repeat */;
 }
 
@@ -139,6 +129,7 @@ int fakeidentd_main(int argc, char **argv)
                xlisten(fd, 5);
        }
 
-       isrv_run(fd, new_peer, do_rd, NULL, do_timeout, TIMEOUT, 1);
+       isrv_run(fd, new_peer, do_rd, /*do_wr:*/ NULL, do_timeout,
+                       TIMEOUT, (opt & OPT_inetdwait) ? TIMEOUT : 0);
        return 0;
 }