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.
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 *);
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.
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;
}
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))
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)
;