From: Markus Armbruster Date: Sat, 10 Mar 2012 12:51:39 +0000 (+0100) Subject: Base idle timeout on player->curup again, not current time X-Git-Tag: v4.3.30~38 X-Git-Url: http://git.pond.sub.org/?p=empserver;a=commitdiff_plain;h=ed1cbc97e66405d9bf7639f56fe4f2f98a2961c0 Base idle timeout on player->curup again, not current time 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. --- diff --git a/include/empio.h b/include/empio.h index 673a857bb..517865053 100644 --- a/include/empio.h +++ b/include/empio.h @@ -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 *); diff --git a/src/lib/empthread/io.c b/src/lib/empthread/io.c index f73d89d5d..b440a4f3e 100644 --- a/src/lib/empthread/io.c +++ b/src/lib/empthread/io.c @@ -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. diff --git a/src/lib/player/accept.c b/src/lib/player/accept.c index 46a6b17c6..ad1e78a0b 100644 --- a/src/lib/player/accept.c +++ b/src/lib/player/accept.c @@ -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; } diff --git a/src/lib/player/login.c b/src/lib/player/login.c index 324d31b5f..61e011d9b 100644 --- a/src/lib/player/login.c +++ b/src/lib/player/login.c @@ -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)) diff --git a/src/lib/player/recvclient.c b/src/lib/player/recvclient.c index 33c3cbbe5..f9e7d5bc8 100644 --- a/src/lib/player/recvclient.c +++ b/src/lib/player/recvclient.c @@ -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) ;