From: Markus Armbruster Date: Sun, 29 Jan 2012 07:52:30 +0000 (+0100) Subject: Fix idle timeout during execute X-Git-Tag: v4.3.30~64 X-Git-Url: http://git.pond.sub.org/?p=empserver;a=commitdiff_plain;h=ca7578f1b80ca46bc4e7d31bb30f39e0f4ee3632 Fix idle timeout during execute Timeout during execute gets handled just like an EOF cookie: end the batch file, resume reading normal commands. That's wrong, we need to close the connection. A real EOF is recorded in the player's connection's EOF indicator. Let's use that for all "connection needs to be closed" conditions, so they all work the same. Create io_set_eof() to provide access. Make recvclient() set the player connection's EOF indicator on timeout. This makes the timeout "stick". Record receipt of an EOF cookie in new struct player member got_ctld. Also abort the command, as before. This leaves further interpretation of the EOF cookie to the command loops. Make player_main() set the player connection's EOF indicator on got_ctld. Player connection gets closed on on EOF cookie, as before. Change execute() to break the batch command loop when got_ctld is set, then reset it. Ends the batch file on EOF cookie, as before. Change status() back to checking EOF and error indicators (partial revert of commit 9c5854c8, v4.3.16), and drop struct player member eof. --- diff --git a/include/empio.h b/include/empio.h index a1675e629..cd51458e8 100644 --- a/include/empio.h +++ b/include/empio.h @@ -57,6 +57,7 @@ extern int io_puts(struct iop *, char *); extern int io_shutdown(struct iop *, int); extern int io_error(struct iop *); extern int io_eof(struct iop *); +extern void io_set_eof(struct iop *); extern int io_fileno(struct iop *); #endif diff --git a/include/player.h b/include/player.h index afe0ec9c2..e6ae8d2a5 100644 --- a/include/player.h +++ b/include/player.h @@ -29,7 +29,7 @@ * Known contributors to this file: * Dave Pare, 1994 * Doug Hay, 1998 - * Markus Armbruster, 2005-2010 + * Markus Armbruster, 2005-2012 */ #ifndef PLAYER_H @@ -81,8 +81,8 @@ struct player { double dolcost; time_t curup; /* when last input was received */ enum player_sleep may_sleep; /* when may thread sleep? */ - int aborted; /* interrupt cookie or EOF received? */ - int eof; /* EOF (cookie or real) received? */ + int aborted; /* command aborted? */ + int got_ctld; /* EOF cookie received? */ int recvfail; /* #recvclient() failures */ int curid; /* for pr, cur. line's id, -1 none */ char *map; /* pointer to in-mem map */ diff --git a/src/lib/empthread/io.c b/src/lib/empthread/io.c index 93e2b02bf..ef285a74c 100644 --- a/src/lib/empthread/io.c +++ b/src/lib/empthread/io.c @@ -29,7 +29,7 @@ * Known contributors to this file: * Doug Hay, 1998 * Steve McClure, 1998 - * Markus Armbruster, 2004-2010 + * Markus Armbruster, 2004-2012 * Ron Koenderink, 2009 */ @@ -131,16 +131,17 @@ io_input(struct iop *iop, int waitforinput) int cc; int res; - /* Not a read IOP */ if ((iop->flags & IO_READ) == 0) { errno = EBADF; return -1; } - /* IOP is markes as in error. */ if (iop->flags & IO_ERROR) { errno = EBADF; return -1; } + if (iop->flags & IO_EOF) + return 0; + /* Wait for the file to have input. */ if (waitforinput) { res = empth_select(iop->fd, EMPTH_FD_READ, &iop->input_timeout); @@ -257,7 +258,6 @@ io_output_if_queue_long(struct iop *iop, int wait) return io_output(iop, wait); } - int io_peek(struct iop *iop, char *buf, int nbytes) { @@ -334,6 +334,17 @@ io_eof(struct iop *iop) return iop->flags & IO_EOF; } +/* + * Discard IOP's buffered input and set its EOF flag. + * No more input can be read from IOP. + */ +void +io_set_eof(struct iop *iop) +{ + ioq_drain(iop->input); + iop->flags |= IO_EOF; +} + int io_fileno(struct iop *iop) { diff --git a/src/lib/player/player.c b/src/lib/player/player.c index 6e568882f..647cb5151 100644 --- a/src/lib/player/player.c +++ b/src/lib/player/player.c @@ -28,7 +28,7 @@ * * Known contributors to this file: * Steve McClure, 2000 - * Markus Armbruster, 2004-2011 + * Markus Armbruster, 2004-2012 * Ron Koenderink, 2004-2009 */ @@ -99,7 +99,9 @@ player_main(struct player *p) } while (status() && command()) { - player->aborted = player->eof; + if (player->got_ctld) + io_set_eof(player->iop); + player->aborted = 0; empth_yield(); } /* #*# I put the following line in to prevent server crash -KHS */ @@ -171,7 +173,8 @@ status(void) time(&player->curup); update_timeused(player->curup); - if (player->eof || player->state == PS_SHUTDOWN + if (io_error(player->iop) || io_eof(player->iop) + || player->state == PS_SHUTDOWN || !may_play_now(natp, player->curup)) return 0; @@ -243,7 +246,7 @@ execute(void) return RET_SYN; prexec(p); - while (!failed && status()) { + while (!failed && status() && !player->got_ctld) { player->nstat &= ~EXEC; if (getcommand(player->combuf) < 0) break; @@ -267,7 +270,7 @@ execute(void) } pr("Execute : %s\n", failed ? "aborted" : "terminated"); - player->eof = 0; + player->got_ctld = 0; return RET_OK; } diff --git a/src/lib/player/recvclient.c b/src/lib/player/recvclient.c index 6ec052a40..ed26acfa3 100644 --- a/src/lib/player/recvclient.c +++ b/src/lib/player/recvclient.c @@ -28,7 +28,7 @@ * * Known contributors to this file: * Dave Pare, 1986 - * Markus Armbruster, 2006-2009 + * Markus Armbruster, 2006-2012 * Ron Koenderink, 2009 */ @@ -47,10 +47,12 @@ * This may block for input, yielding the processor. Flush buffered * output when blocking, to make sure player sees the prompt. * If the player's connection has the I/O error or EOF indicator set, - * or we block and time out, or the line is "ctld", set the player's - * eof and aborted flag and return -1. - * If the line is "aborted", set the player's aborted flag and return + * or the line is "aborted", set the player's aborted flag and return * -1. + * If we block and time out, set the EOF indicator on the player's + * connection, set the player's aborted flag, and return -1. + * If the line is "ctld", set the player's eof and aborted flag and + * return -1. * Else return the length of the line. * Design bug: there is no way to indicate truncation of a long line. */ @@ -66,7 +68,7 @@ recvclient(char *cmd, int size) if (count >= 0) { /* got it */ if (strcmp(cmd, "ctld") == 0) - player->aborted = player->eof = 1; + player->aborted = player->got_ctld = 1; if (strcmp(cmd, "aborted") == 0) player->aborted = 1; journal_input(cmd); @@ -92,12 +94,13 @@ recvclient(char *cmd, int size) if (res > 0) ; else if (res < 0) - player->aborted = player->eof = 1; + player->aborted = 1; else if (io_eof(player->iop)) - player->aborted = player->eof = 1; + player->aborted = 1; else if (!player->aborted) { pr_flash(player, "idle connection terminated\n"); - player->aborted = player->eof = 1; + io_set_eof(player->iop); + player->aborted = 1; } }