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.
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
* Known contributors to this file:
* Dave Pare, 1994
* Doug Hay, 1998
- * Markus Armbruster, 2005-2010
+ * Markus Armbruster, 2005-2012
*/
#ifndef PLAYER_H
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 */
* Known contributors to this file:
* Doug Hay, 1998
* Steve McClure, 1998
- * Markus Armbruster, 2004-2010
+ * Markus Armbruster, 2004-2012
* Ron Koenderink, 2009
*/
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);
return io_output(iop, wait);
}
-
int
io_peek(struct iop *iop, char *buf, int nbytes)
{
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)
{
*
* Known contributors to this file:
* Steve McClure, 2000
- * Markus Armbruster, 2004-2011
+ * Markus Armbruster, 2004-2012
* Ron Koenderink, 2004-2009
*/
}
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 */
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;
return RET_SYN;
prexec(p);
- while (!failed && status()) {
+ while (!failed && status() && !player->got_ctld) {
player->nstat &= ~EXEC;
if (getcommand(player->combuf) < 0)
break;
}
pr("Execute : %s\n", failed ? "aborted" : "terminated");
- player->eof = 0;
+ player->got_ctld = 0;
return RET_OK;
}
*
* Known contributors to this file:
* Dave Pare, 1986
- * Markus Armbruster, 2006-2009
+ * Markus Armbruster, 2006-2012
* Ron Koenderink, 2009
*/
* 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.
*/
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);
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;
}
}