Fix idle timeout during execute
authorMarkus Armbruster <armbru@pond.sub.org>
Sun, 29 Jan 2012 07:52:30 +0000 (08:52 +0100)
committerMarkus Armbruster <armbru@pond.sub.org>
Tue, 21 Feb 2012 17:10:52 +0000 (18:10 +0100)
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.

include/empio.h
include/player.h
src/lib/empthread/io.c
src/lib/player/player.c
src/lib/player/recvclient.c

index a1675e629e07473134b195f097b1f0da079b3b46..cd51458e8d6e23f301aa5a79f06f1d793ecaf3ad 100644 (file)
@@ -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
index afe0ec9c2fcf80a35a68815776c35f75c7668c6e..e6ae8d2a5afaa6fb70acd22b7cb990529902363a 100644 (file)
@@ -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 */
index 93e2b02bf7b9c2cf1c2a4ba3130544dfa317aa5e..ef285a74c4a67f1104b8339e9e70a83e43527a88 100644 (file)
@@ -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)
 {
index 6e568882f83073b5e59440ad217ca7bcb3729f2b..647cb51516f239ba3289e248276b3533310f48fb 100644 (file)
@@ -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;
 }
 
index 6ec052a40a6c144f36c91f95f087169f21086b9f..ed26acfa35fe0bf698dcf12c192c7b28d3dcde58 100644 (file)
@@ -28,7 +28,7 @@
  *
  *  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.
  */
@@ -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;
        }
     }