]> git.pond.sub.org Git - empserver/commitdiff
Oops when player thread keeps reading input unsuccessfully
authorMarkus Armbruster <armbru@pond.sub.org>
Sun, 13 Jul 2008 02:41:52 +0000 (22:41 -0400)
committerMarkus Armbruster <armbru@pond.sub.org>
Sun, 13 Jul 2008 11:50:20 +0000 (07:50 -0400)
Reading input fails after EOF and while the current command is
aborted.  Commands should detect that and fail.  If a command neglects
to do that in a loop, the loop can become infinite.  This is
especially bad after EOF, because then the client might not read
output anymore.  Output gets buffered until memory runs out.

Mitigate such bugs by counting how many calls have failed in a row,
oopsing on the 256th, and sleeping one minute from the 256th on.

include/player.h
src/lib/player/recvclient.c

index 584c613f6dd51fdc7b461e18e53da412b2b3714d..52edb3364362c471023beb5a79a76bff3d6e2f70 100644 (file)
@@ -78,6 +78,7 @@ struct player {
     time_t curup;              /* when last input was received */
     int aborted;               /* interrupt cookie received? */
     int eof;                   /* EOF (cookie or real) received? */
+    int recvfail;              /* #recvclient() failures */
     int curid;                 /* for pr, cur. line's id, -1 none */
     char *map;                 /* pointer to in-mem map */
     char *bmap;                        /* pointer to in-mem bmap */
index bda3c37a0ff58bad65dd875647cb424d9633cef4..72730cee6978f619fdf606bac11e9a5443a06e3e 100644 (file)
@@ -91,10 +91,19 @@ recvclient(char *cmd, int size)
            player->eof = 1;
     }
 
-    if (player->eof)
-       return -1;
-    if (player->aborted)
-       return -2;
+    if (player->aborted || player->eof) {
+       player->recvfail++;
+       if (player->recvfail > 255) {
+           /*
+            * Looks like the thread is stuck in a loop that fails to
+            * check errors; oops once, then slow it down drastically.
+            */
+           CANT_HAPPEN(player->recvfail == 256);
+           empth_sleep(time(NULL) + 60);
+       }
+       return player->eof ? -1 : -2;
+    }
 
+    player->recvfail = 0;
     return count;
 }