From: Markus Armbruster Date: Sun, 6 Nov 2016 16:05:19 +0000 (+0100) Subject: client: Fix obscure readline hang X-Git-Tag: v4.4.0~65^2~11 X-Git-Url: http://git.pond.sub.org/?p=empserver;a=commitdiff_plain;h=5e82836e3a74d1e0d30510b24ad0582f0a960652 client: Fix obscure readline hang 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 --- diff --git a/src/client/play.c b/src/client/play.c index f02399bab..2684a2b9f 100644 --- a/src/client/play.c +++ b/src/client/play.c @@ -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; }