]> git.pond.sub.org Git - empserver/commitdiff
client: Fix obscure readline hang
authorMarkus Armbruster <armbru@pond.sub.org>
Sun, 6 Nov 2016 16:05:19 +0000 (17:05 +0100)
committerMarkus Armbruster <armbru@pond.sub.org>
Sun, 6 Aug 2017 09:22:29 +0000 (11:22 +0200)
If recv_input() can't stuff the whole line into @inbuf, it leaves its
tail in @input_from_rl.  If send_input() then empties @inbuf, the next
iteration will select @input_fd for reading instead of @sock for
writing, because @inbuf is empty.  Since @has_rl_input is still set,
recv_input() will do nothing, and the client hangs.

Fix as follows.  Factor ring_from_rl() out of recv_input().  Also call
it in send_input() to refill @inbuf from @input_from_rl.

Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
src/client/play.c

index f02399bab8439c106abedf9b2179f259735ddf03..2684a2b9f033fda2a677dd0f8046f52aa547316c 100644 (file)
@@ -451,6 +451,32 @@ input_handler(char *line)
        add_history(line);
 #endif /* HAVE_READLINE_HISTORY */
 }
+
+static int
+ring_from_rl(struct ring *inbuf)
+{
+    size_t len;
+    int n;
+
+    assert(has_rl_input && input_from_rl);
+
+    len = strlen(input_from_rl);
+    n = ring_space(inbuf);
+    assert(n);
+
+    if (len >= (size_t)n) {
+       ring_putm(inbuf, input_from_rl, n);
+       memmove(input_from_rl, input_from_rl + n, len - n + 1);
+    } else {
+       ring_putm(inbuf, input_from_rl, len);
+       ring_putc(inbuf, '\n');
+       free(input_from_rl);
+       has_rl_input = 0;
+       n = len + 1;
+    }
+
+    return n;
+}
 #endif /* HAVE_LIBREADLINE */
 
 /*
@@ -462,28 +488,15 @@ recv_input(int fd, struct ring *inbuf)
 {
     int n;
     int res = 1;
-#ifdef HAVE_LIBREADLINE
-    size_t len;
 
+#ifdef HAVE_LIBREADLINE
     if (fd == 0) {
        if (!has_rl_input)
            rl_callback_read_char();
        if (!has_rl_input)
            return 1;
        if (input_from_rl) {
-           len = strlen(input_from_rl);
-           n = ring_space(inbuf);
-           assert(n);
-           if (len >= (size_t)n) {
-               ring_putm(inbuf, input_from_rl, n);
-               memmove(input_from_rl, input_from_rl + n, len - n + 1);
-           } else {
-               ring_putm(inbuf, input_from_rl, len);
-               ring_putc(inbuf, '\n');
-               free(input_from_rl);
-               has_rl_input = 0;
-               n = len + 1;
-           }
+           n = ring_from_rl(inbuf);
        } else
            n = 0;
     } else
@@ -524,6 +537,11 @@ send_input(int fd, struct ring *inbuf)
            putc(ch, auxfp);
     }
 
+#ifdef HAVE_LIBREADLINE
+    if (fd == 0 && has_rl_input && input_from_rl)
+       ring_from_rl(inbuf);
+#endif
+
     return res;
 }