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.
This commit is contained in:
Markus Armbruster 2012-01-29 08:52:30 +01:00
parent d78d9cac1d
commit ca7578f1b8
5 changed files with 38 additions and 20 deletions

View file

@ -57,6 +57,7 @@ extern int io_puts(struct iop *, char *);
extern int io_shutdown(struct iop *, int); extern int io_shutdown(struct iop *, int);
extern int io_error(struct iop *); extern int io_error(struct iop *);
extern int io_eof(struct iop *); extern int io_eof(struct iop *);
extern void io_set_eof(struct iop *);
extern int io_fileno(struct iop *); extern int io_fileno(struct iop *);
#endif #endif

View file

@ -29,7 +29,7 @@
* Known contributors to this file: * Known contributors to this file:
* Dave Pare, 1994 * Dave Pare, 1994
* Doug Hay, 1998 * Doug Hay, 1998
* Markus Armbruster, 2005-2010 * Markus Armbruster, 2005-2012
*/ */
#ifndef PLAYER_H #ifndef PLAYER_H
@ -81,8 +81,8 @@ struct player {
double dolcost; double dolcost;
time_t curup; /* when last input was received */ time_t curup; /* when last input was received */
enum player_sleep may_sleep; /* when may thread sleep? */ enum player_sleep may_sleep; /* when may thread sleep? */
int aborted; /* interrupt cookie or EOF received? */ int aborted; /* command aborted? */
int eof; /* EOF (cookie or real) received? */ int got_ctld; /* EOF cookie received? */
int recvfail; /* #recvclient() failures */ int recvfail; /* #recvclient() failures */
int curid; /* for pr, cur. line's id, -1 none */ int curid; /* for pr, cur. line's id, -1 none */
char *map; /* pointer to in-mem map */ char *map; /* pointer to in-mem map */

View file

@ -29,7 +29,7 @@
* Known contributors to this file: * Known contributors to this file:
* Doug Hay, 1998 * Doug Hay, 1998
* Steve McClure, 1998 * Steve McClure, 1998
* Markus Armbruster, 2004-2010 * Markus Armbruster, 2004-2012
* Ron Koenderink, 2009 * Ron Koenderink, 2009
*/ */
@ -131,16 +131,17 @@ io_input(struct iop *iop, int waitforinput)
int cc; int cc;
int res; int res;
/* Not a read IOP */
if ((iop->flags & IO_READ) == 0) { if ((iop->flags & IO_READ) == 0) {
errno = EBADF; errno = EBADF;
return -1; return -1;
} }
/* IOP is markes as in error. */
if (iop->flags & IO_ERROR) { if (iop->flags & IO_ERROR) {
errno = EBADF; errno = EBADF;
return -1; return -1;
} }
if (iop->flags & IO_EOF)
return 0;
/* Wait for the file to have input. */ /* Wait for the file to have input. */
if (waitforinput) { if (waitforinput) {
res = empth_select(iop->fd, EMPTH_FD_READ, &iop->input_timeout); 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); return io_output(iop, wait);
} }
int int
io_peek(struct iop *iop, char *buf, int nbytes) io_peek(struct iop *iop, char *buf, int nbytes)
{ {
@ -334,6 +334,17 @@ io_eof(struct iop *iop)
return iop->flags & IO_EOF; 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 int
io_fileno(struct iop *iop) io_fileno(struct iop *iop)
{ {

View file

@ -28,7 +28,7 @@
* *
* Known contributors to this file: * Known contributors to this file:
* Steve McClure, 2000 * Steve McClure, 2000
* Markus Armbruster, 2004-2011 * Markus Armbruster, 2004-2012
* Ron Koenderink, 2004-2009 * Ron Koenderink, 2004-2009
*/ */
@ -99,7 +99,9 @@ player_main(struct player *p)
} }
while (status() && command()) { while (status() && command()) {
player->aborted = player->eof; if (player->got_ctld)
io_set_eof(player->iop);
player->aborted = 0;
empth_yield(); empth_yield();
} }
/* #*# I put the following line in to prevent server crash -KHS */ /* #*# I put the following line in to prevent server crash -KHS */
@ -171,7 +173,8 @@ status(void)
time(&player->curup); time(&player->curup);
update_timeused(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)) || !may_play_now(natp, player->curup))
return 0; return 0;
@ -243,7 +246,7 @@ execute(void)
return RET_SYN; return RET_SYN;
prexec(p); prexec(p);
while (!failed && status()) { while (!failed && status() && !player->got_ctld) {
player->nstat &= ~EXEC; player->nstat &= ~EXEC;
if (getcommand(player->combuf) < 0) if (getcommand(player->combuf) < 0)
break; break;
@ -267,7 +270,7 @@ execute(void)
} }
pr("Execute : %s\n", failed ? "aborted" : "terminated"); pr("Execute : %s\n", failed ? "aborted" : "terminated");
player->eof = 0; player->got_ctld = 0;
return RET_OK; return RET_OK;
} }

View file

@ -28,7 +28,7 @@
* *
* Known contributors to this file: * Known contributors to this file:
* Dave Pare, 1986 * Dave Pare, 1986
* Markus Armbruster, 2006-2009 * Markus Armbruster, 2006-2012
* Ron Koenderink, 2009 * Ron Koenderink, 2009
*/ */
@ -47,10 +47,12 @@
* This may block for input, yielding the processor. Flush buffered * This may block for input, yielding the processor. Flush buffered
* output when blocking, to make sure player sees the prompt. * output when blocking, to make sure player sees the prompt.
* If the player's connection has the I/O error or EOF indicator set, * 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 * or the line is "aborted", set the player's aborted flag and return
* eof and aborted flag and return -1.
* If the line is "aborted", set the player's aborted flag and return
* -1. * -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. * Else return the length of the line.
* Design bug: there is no way to indicate truncation of a long 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) { if (count >= 0) {
/* got it */ /* got it */
if (strcmp(cmd, "ctld") == 0) if (strcmp(cmd, "ctld") == 0)
player->aborted = player->eof = 1; player->aborted = player->got_ctld = 1;
if (strcmp(cmd, "aborted") == 0) if (strcmp(cmd, "aborted") == 0)
player->aborted = 1; player->aborted = 1;
journal_input(cmd); journal_input(cmd);
@ -92,12 +94,13 @@ recvclient(char *cmd, int size)
if (res > 0) if (res > 0)
; ;
else if (res < 0) else if (res < 0)
player->aborted = player->eof = 1; player->aborted = 1;
else if (io_eof(player->iop)) else if (io_eof(player->iop))
player->aborted = player->eof = 1; player->aborted = 1;
else if (!player->aborted) { else if (!player->aborted) {
pr_flash(player, "idle connection terminated\n"); pr_flash(player, "idle connection terminated\n");
player->aborted = player->eof = 1; io_set_eof(player->iop);
player->aborted = 1;
} }
} }