Base idle timeout on player->curup again, not current time
authorMarkus Armbruster <armbru@pond.sub.org>
Sat, 10 Mar 2012 12:51:39 +0000 (13:51 +0100)
committerMarkus Armbruster <armbru@pond.sub.org>
Tue, 27 Mar 2012 15:23:18 +0000 (17:23 +0200)
Idle timeout used to expire max_idle minutes after the last
player->curup update.  When we got rid of the idle thread in commit
08b94556 (v4.3.20), this got changed to "wait no more than max_idle
minutes for input".  Time spent computing and time spent blocked on
output no longer counts.  In particular, a connection can block
indefinitely on output since then.  Let's fix that.

Start with basing the input timeout on player->curup again.  The
missing output timeout will be added shortly.

Aside: since status() updates player->curup, the idle timer gets reset
when the update aborts a command.  Left for another day.

include/empio.h
src/lib/empthread/io.c
src/lib/player/accept.c
src/lib/player/login.c
src/lib/player/recvclient.c

index 673a857bbe54db62089032cda87d12b4c30fc08d..51786505352cafe0e31e6032a4a6e9d0a57633b2 100644 (file)
@@ -44,6 +44,7 @@
 extern struct iop *io_open(int, int, int);
 extern void io_init(void);
 extern void io_close(struct iop *, struct timeval *);
+extern void io_timeout(struct timeval *, time_t);
 extern int io_input(struct iop *, struct timeval *);
 extern int io_inputwaiting(struct iop *);
 extern int io_outputwaiting(struct iop *);
index f73d89d5dd28db6c8d18e55c1852349321e9829c..b440a4f3e5cbfd0add227d018734f03bf561ee94 100644 (file)
@@ -124,6 +124,24 @@ io_close(struct iop *iop, struct timeval *timeout)
     free(iop);
 }
 
+void
+io_timeout(struct timeval *timeout, time_t deadline)
+{
+    struct timeval now;
+
+    gettimeofday(&now, NULL);
+    if (now.tv_sec >= deadline) {
+       /* deadline reached already */
+       timeout->tv_sec = 0;
+       timeout->tv_usec = 0;
+    } else {
+       /* deadline in future */
+       timeout->tv_sec = deadline - now.tv_sec - 1;
+       timeout->tv_usec = 999999 - now.tv_usec;
+       /* yes, this is 1usec early; sue me */
+    }
+}
+
 /*
  * Read input from IOP and enqueue it.
  * If TIMEOUT is non-null, wait at most that long for input to arrive.
index 46a6b17c6d1d50a3ae0d63b066169e1151e15e10..ad1e78a0bef1e5405aa715c82e708a82b51050bc 100644 (file)
@@ -100,8 +100,7 @@ player_delete(struct player *lp)
 
     if (lp->iop) {
        /* it's a real player */
-       timeout.tv_sec = minutes(max_idle);
-       timeout.tv_usec = 0;
+       io_timeout(&timeout, player->curup + minutes(max_idle));
        io_close(lp->iop, &timeout);
        lp->iop = NULL;
     }
index 324d31b5f856757e79bc5aac908abecce35c5126..61e011d9bb17d6d0e101a95dbd16a1ea1a180008 100644 (file)
@@ -90,8 +90,7 @@ player_login(void *ud)
     for (;;) {
        io_output(player->iop, 1);
        if (io_gets(player->iop, buf, sizeof(buf)) < 0) {
-           timeout.tv_sec = minutes(max_idle);
-           timeout.tv_usec = 0;
+           io_timeout(&timeout, player->curup + minutes(max_idle));
            res = io_input(player->iop, &timeout);
            if (res <= 0) {
                if (res == 0 && !io_eof(player->iop))
index 33c3cbbe53ef9bef39ae424215f77f15db74f739..f9e7d5bc8801a18ab8afee307ccd8d6822512edc 100644 (file)
@@ -92,8 +92,7 @@ recvclient(char *cmd, int size)
        if (player->aborted)
            break;
 
-       timeout.tv_sec = minutes(max_idle);
-       timeout.tv_usec = 0;
+       io_timeout(&timeout, player->curup + minutes(max_idle));
        res = io_input(player->iop, &timeout);
        if (res > 0)
            ;