diff --git a/include/empio.h b/include/empio.h index a1675e62..cd51458e 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 afe0ec9c..e6ae8d2a 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 93e2b02b..ef285a74 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 6e568882..647cb515 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 6ec052a4..ed26acfa 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; } }