From: Roman Zippel > Does that make sense to you? Maybe the "input full, but no canon_data" > special case would be better handled in the read path, rather than the > write path? There might be no reader at this time. The basic problem is that this should be handled in the receive_buf path, but for that it had to return the numbers of characters written (or dropped in the no canon_data case). Relying on receive_room value instead is rather bogus. Below is a new patch, which also fixes problems with very long lines. 1. if receive_room() returns a small number, write_chan() has to continue writing, otherwise it will sleep with nobody waking it up. 2. we mustn't simply drop eol characters in n_tty_receive_char otherwise canon_data isn't increased and the reader isn't woken up. Alan said: The problem looks valid. The behaviour of 'traditional unix' appears to be the following If you exceed the line limit then beep and drop the character Always allow EOL to complete a canonical line input Always do signal/control processing if enabled Signed-off-by: Andrew Morton --- 25-akpm/drivers/char/n_tty.c | 33 +++++++++++++++------------------ 1 files changed, 15 insertions(+), 18 deletions(-) diff -puN drivers/char/n_tty.c~tty-output-lossage-fix drivers/char/n_tty.c --- 25/drivers/char/n_tty.c~tty-output-lossage-fix 2005-03-16 21:42:03.000000000 -0800 +++ 25-akpm/drivers/char/n_tty.c 2005-03-16 21:42:03.000000000 -0800 @@ -770,10 +770,8 @@ send_signal: } if (c == '\n') { if (L_ECHO(tty) || L_ECHONL(tty)) { - if (tty->read_cnt >= N_TTY_BUF_SIZE-1) { + if (tty->read_cnt >= N_TTY_BUF_SIZE-1) put_char('\a', tty); - return; - } opost('\n', tty); } goto handle_newline; @@ -790,10 +788,8 @@ send_signal: * XXX are EOL_CHAR and EOL2_CHAR echoed?!? */ if (L_ECHO(tty)) { - if (tty->read_cnt >= N_TTY_BUF_SIZE-1) { + if (tty->read_cnt >= N_TTY_BUF_SIZE-1) put_char('\a', tty); - return; - } /* Record the column of first canon char. */ if (tty->canon_head == tty->read_head) tty->canon_column = tty->column; @@ -862,12 +858,9 @@ static int n_tty_receive_room(struct tty * that erase characters will be handled. Other excess * characters will be beeped. */ - if (tty->icanon && !tty->canon_data) - return N_TTY_BUF_SIZE; - - if (left > 0) - return left; - return 0; + if (left <= 0) + left = tty->icanon && !tty->canon_data; + return left; } /** @@ -1473,13 +1466,17 @@ static ssize_t write_chan(struct tty_str if (tty->driver->flush_chars) tty->driver->flush_chars(tty); } else { - c = tty->driver->write(tty, b, nr); - if (c < 0) { - retval = c; - goto break_out; + while (nr > 0) { + c = tty->driver->write(tty, b, nr); + if (c < 0) { + retval = c; + goto break_out; + } + if (!c) + break; + b += c; + nr -= c; } - b += c; - nr -= c; } if (!nr) break; _