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 <armbru@pond.sub.org>
This commit is contained in:
parent
0cb6690600
commit
5e82836e3a
1 changed files with 33 additions and 15 deletions
|
@ -451,6 +451,32 @@ input_handler(char *line)
|
||||||
add_history(line);
|
add_history(line);
|
||||||
#endif /* HAVE_READLINE_HISTORY */
|
#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 */
|
#endif /* HAVE_LIBREADLINE */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -462,28 +488,15 @@ recv_input(int fd, struct ring *inbuf)
|
||||||
{
|
{
|
||||||
int n;
|
int n;
|
||||||
int res = 1;
|
int res = 1;
|
||||||
#ifdef HAVE_LIBREADLINE
|
|
||||||
size_t len;
|
|
||||||
|
|
||||||
|
#ifdef HAVE_LIBREADLINE
|
||||||
if (fd == 0) {
|
if (fd == 0) {
|
||||||
if (!has_rl_input)
|
if (!has_rl_input)
|
||||||
rl_callback_read_char();
|
rl_callback_read_char();
|
||||||
if (!has_rl_input)
|
if (!has_rl_input)
|
||||||
return 1;
|
return 1;
|
||||||
if (input_from_rl) {
|
if (input_from_rl) {
|
||||||
len = strlen(input_from_rl);
|
n = ring_from_rl(inbuf);
|
||||||
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;
|
|
||||||
}
|
|
||||||
} else
|
} else
|
||||||
n = 0;
|
n = 0;
|
||||||
} else
|
} else
|
||||||
|
@ -524,6 +537,11 @@ send_input(int fd, struct ring *inbuf)
|
||||||
putc(ch, auxfp);
|
putc(ch, auxfp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef HAVE_LIBREADLINE
|
||||||
|
if (fd == 0 && has_rl_input && input_from_rl)
|
||||||
|
ring_from_rl(inbuf);
|
||||||
|
#endif
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue