From: Maximiliano Curia <maxy@gnuservers.com.ar>
To: linux-kernel@vger.kernel.org
Subject: Re: Large pastes into readline enabled programs causes breakage from v2.6.31 onwards
Date: Tue, 30 Jul 2013 14:41:14 +0200 [thread overview]
Message-ID: <asokca-mgs.ln1@freak.gnuservers.com.ar> (raw)
In-Reply-To: 51F1B015.50804@hurleysoftware.com
Peter Hurley wrote:
> readline is fundamentally incompatible with an active writer.
This wasn't the case with older kernel versions. I don't see any POSIX
reference that claims user input could be lost setting termios so I think
this is a serious regression.
Also, consider the readline use cases. bash, for instance, uses readline to
process the command lines entered, but needs to change the termios to a
canonical mode for each entered command. I would expect that pasting a
sequence of commands (of 4K, which is not even 'a lot') to work.
The same is true for psql, where users might paste several KB of queries, or
almost every readline enabled "shell".
> readline() saves and restores the termios settings for each input
> line it reads. However, tty i/o is asynchronous in the kernel.
> This means that when readline() restores the original termios
> settings, any new data received by the tty will be interpreted
> with the current, original termios settings.
> When a large paste happens, the tty/line discipline read buffer
> quickly fills up (to 4k). When full, further input is forced to
> wait. After readline() reads an input line, more space becomes
> available in the read buffer. Unfortunately, this event roughly
> coincides with restoring the original termios settings, and
> thus increases the probability that more paste data will be
> received with the wrong termios settings.
> That's why the patches that involve scheduling the receive
> buffer work seem to have some effect on the outcome.
It's not totally clear to me why receiving characters with the wrong termios
settings might lead to this characters being dropped when reading them with
different settings.
I took a deep look into the code, trying to find where was the code that ended
up dropping characters, but could not find it.
Could you maybe point me to it?
> As you've already noted, readline() termios settings are
> substantially different than the default termios settings.
>
> Below I've included a simple test jig that
> 1) sets termios to the same settings as readline()
> 2) uses the same read() method as readline()
> 3) outputs what it reads to stdout
> 4) restores the original termios
I've updated your code the be closer to the readline behaviour. readline
calls tcsetattr with TCSADRAIN, and not TCSAFLUSH which explictly claims to
discard the input. I've also reordered the call to process lines, and
initialized the int c.
--- >% ---
#include <stdio.h>
#include <termios.h>
#include <unistd.h>
#include <stdlib.h>
void init(int *eof, struct termios* save)
{
int err;
static struct termios termios;
err = tcgetattr(STDIN_FILENO, &termios);
if (err < 0)
exit(EXIT_FAILURE);
*save = termios;
termios.c_lflag &= ~(ICANON | ECHO | ISIG);
termios.c_iflag &= ~(IXON | IXOFF);
if ((termios.c_cflag & CSIZE) == CS8)
termios.c_iflag &= ~(ISTRIP | INPCK);
termios.c_iflag &= ~(ICRNL | INLCR);
termios.c_cc[VMIN] = 1;
termios.c_cc[VTIME] = 0;
termios.c_cc[VLNEXT] = _POSIX_VDISABLE;
*eof = termios.c_cc[VEOF];
err = tcsetattr(STDIN_FILENO, TCSADRAIN, &termios);
if (err < 0)
exit(EXIT_FAILURE);
}
void deinit(struct termios* termios)
{
int err;
err = tcsetattr(STDIN_FILENO, TCSADRAIN, termios);
if (err < 0)
exit(EXIT_FAILURE);
}
int main(int argc, char* argv[])
{
int c=0, eof;
ssize_t actual;
struct termios save;
while (1) {
init(&eof, &save);
while (1) {
actual = read(fileno(stdin), &c, sizeof(unsigned char));
if (actual <= 0)
break;
if (actual == sizeof(unsigned char)) {
if (c == eof)
break;
if (c == '\r') {
c = '\n';
}
fputc(c, stdout);
fflush(stdout);
if (c == '\n') break;
}
}
deinit(&save);
if (c == eof) break;
}
return 0;
}
--- >% ---
--
"Seek simplicity, and distrust it." -- Whitehead's Rule
Saludos /\/\ /\ >< `/
next prev parent reply other threads:[~2013-07-30 13:15 UTC|newest]
Thread overview: 40+ messages / expand[flat|nested] mbox.gz Atom feed top
2013-07-25 11:29 Large pastes into readline enabled programs causes breakage from v2.6.31 onwards Margarita Manterola
2013-07-25 23:09 ` Peter Hurley
2013-07-30 12:41 ` Maximiliano Curia [this message]
[not found] ` <20130730124117.41DC55E4006@freak.gnuservers.com.ar>
2013-07-30 16:08 ` Peter Hurley
2013-08-08 17:58 ` Maximiliano Curia
2013-08-17 15:28 ` Pavel Machek
2013-08-17 22:57 ` Margarita Manterola
2013-08-18 8:08 ` Geert Uytterhoeven
2013-09-03 5:17 ` Arkadiusz Miskiewicz
2013-10-24 16:00 ` Arkadiusz Miskiewicz
2013-10-29 13:50 ` Maximiliano Curia
2013-10-30 11:21 ` Peter Hurley
2013-11-17 18:29 ` Pavel Machek
2013-11-17 21:38 ` Margarita Manterola
2013-11-21 5:04 ` Peter Hurley
2013-11-22 12:57 ` Peter Hurley
2013-11-24 0:29 ` One Thousand Gnomes
2013-11-24 11:55 ` Peter Hurley
2013-11-26 1:16 ` Peter Hurley
2013-12-03 0:18 ` Peter Hurley
2013-12-03 9:01 ` Stas Sergeev
2013-12-03 17:00 ` Peter Hurley
2013-12-03 19:18 ` Stas Sergeev
2013-12-03 23:53 ` Peter Hurley
2013-12-04 18:57 ` Stas Sergeev
2013-12-09 14:50 ` [PATCH v3] n_tty: Fix buffer overruns with larger-than-4k pastes Peter Hurley
[not found] ` <52A5EF3F.2070805@list.ru>
2013-12-09 17:10 ` Peter Hurley
2013-12-10 6:15 ` Stas Sergeev
2013-12-10 22:05 ` Peter Hurley
2013-12-10 22:12 ` [PATCH v4] " Peter Hurley
2013-12-17 0:57 ` Greg Kroah-Hartman
2013-12-17 1:24 ` Peter Hurley
2013-12-18 11:48 ` Henrique de Moraes Holschuh
2013-12-18 13:41 ` Peter Hurley
2014-01-28 12:03 ` Large pastes into readline enabled programs causes breakage from v2.6.31 onwards Pavel Machek
2014-01-28 12:17 ` Stas Sergeev
2014-01-28 13:31 ` Peter Hurley
2013-08-19 12:25 ` Peter Hurley
2013-09-03 21:12 ` Maximiliano Curia
2013-09-12 1:36 ` Peter Hurley
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=asokca-mgs.ln1@freak.gnuservers.com.ar \
--to=maxy@gnuservers.com.ar \
--cc=linux-kernel@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.