Bug 55991 - [PATCH]n_tty: keep the data written in raw mode still available to read after icanon is enabled
Summary: [PATCH]n_tty: keep the data written in raw mode still available to read afte...
Status: CLOSED CODE_FIX
Alias: None
Product: Drivers
Classification: Unclassified
Component: Other (show other bugs)
Hardware: All Linux
: P1 normal
Assignee: Alan
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2013-03-30 15:09 UTC by Stas Sergeev
Modified: 2014-01-20 19:12 UTC (History)
3 users (show)

See Also:
Kernel Version: 3.x
Subsystem:
Regression: No
Bisected commit-id:


Attachments
the fix (1.26 KB, patch)
2013-03-30 15:09 UTC, Stas Sergeev
Details | Diff
testcase (2.85 KB, text/x-csrc)
2013-11-25 16:08 UTC, Peter Hurley
Details
Proposed patch (2.45 KB, patch)
2013-11-25 16:14 UTC, Peter Hurley
Details | Diff
Proposed patch v2 (3.13 KB, patch)
2013-11-25 20:16 UTC, Peter Hurley
Details | Diff

Description Stas Sergeev 2013-03-30 15:09:50 UTC
Created attachment 96691 [details]
the fix

If icanon is enabled while the data written in raw mode
is still pending, currently it won't be read.
The attached patch fixes the problem.
Comment 1 Peter Hurley 2013-11-24 11:55:32 UTC
Thanks for the proposal.

Unfortunately, simulating an EOF push when switching from non-canonical to canonical mode assumes that the input will actually now be read in canonical mode. However, that may not be true.

For example, an application using readline() for all its input will loop, calling readline(). Since readline() switches to non-canonical to perform char-by-char reads and then restores the original termios settings before
returning to the caller, any typeahead or paste read on the next iteration would be corrupted by the '\0'.
Comment 2 Stas Sergeev 2013-11-24 12:26:38 UTC
Yes, that's not very good.
The result of allowing the patches to hang
for so long, is that I don't remember the
code very well now, and probably have lost the
test-case...
Looking at the code now, I think the patch can
just be changed as follows:
+ set_bit(ldata->read_head, ldata->read_flags);
should be changed to
+ set_bit(ldata->read_head - 1, ldata->read_flags);

and the
+ put_tty_queue(__DISABLED_CHAR, ldata);
can then just be removed. It seems, the code handles
that case very well and will not be confused by
the lack of __DISABLED_CHAR.

I don't know however when I recover the test-case
to test that proposal...
Comment 3 Peter Hurley 2013-11-25 16:08:27 UTC
Created attachment 115941 [details]
testcase
Comment 4 Peter Hurley 2013-11-25 16:14:52 UTC
Created attachment 115951 [details]
Proposed patch

Let me know if this works for you and I'll submit it to linux-kernel.
Comment 5 Peter Hurley 2013-11-25 20:16:33 UTC
Created attachment 116081 [details]
Proposed patch v2
Comment 6 Stas Sergeev 2013-11-25 20:31:42 UTC
Hello Peter, thanks for taking that!
So it seems the code have changed a lot...
Why does read_head now need &(N_TTY_BUF_SIZE - 1)
everywhere, instead of just keeping it in
0...N_TTY_BUF_SIZE-1 range, as before? Does
this mean it can eventually overflow around size_t
with some data loss in buffer?

While I was typing about the strange logic in the patch,
you already replaced it with V2. :)
I won't be able to test it any soon though, but it looks good.

Acked-by: Stas Sergeev <stsp@users.sourceforge.net>
Comment 7 Stas Sergeev 2013-11-25 20:41:46 UTC
By the way, can someone please suggest
me the way to flush the icanon data to
the reader without adding EOL?
Doing that with different EOLs (like VEOL/VEOL2)
is inappropriate as they are being passed
to the reader.
VEOF is not being passed to reader, but it
will produce EOF if no data is available...
That's why I started in my program to switch
between the raw and icanon mode, and so is this
patch. But that's hackish. Any clean way to
flush the icanon data?
Comment 8 Peter Hurley 2013-11-25 21:15:00 UTC
(In reply to Stas Sergeev from comment #6)
> Hello Peter, thanks for taking that!
> So it seems the code have changed a lot...
> Why does read_head now need &(N_TTY_BUF_SIZE - 1)
> everywhere, instead of just keeping it in
> 0...N_TTY_BUF_SIZE-1 range, as before? Does
> this mean it can eventually overflow around size_t
> with some data loss in buffer?

The read_buf is now shared locklessly between the input
processing worker thread (the receive_buf() method which is a
single producer) and the reader (single consumer).

The unsigned overflow arithmetic allows the shared buffer
indices to be updated without locks.

> While I was typing about the strange logic in the patch,
> you already replaced it with V2. :)

Yep, discovered the sudo breakage readily enough :)

> I won't be able to test it any soon though, but it looks good.
>
> Acked-by: Stas Sergeev <stsp@users.sourceforge.net>

Thanks. You'll be cc'd a copy of the proposed from the mailing
list shortly.

PS - The patch should apply to 3.12 with 'git am -C1 <patch_file_name>'
Comment 9 Peter Hurley 2013-11-26 00:57:30 UTC
(In reply to Stas Sergeev from comment #7)
> By the way, can someone please suggest
> me the way to flush the icanon data to
> the reader without adding EOL?
> Doing that with different EOLs (like VEOL/VEOL2)
> is inappropriate as they are being passed
> to the reader.
> VEOF is not being passed to reader, but it
> will produce EOF if no data is available...
> That's why I started in my program to switch
> between the raw and icanon mode, and so is this
> patch. But that's hackish. Any clean way to
> flush the icanon data?

Not that I know of, sorry.
Comment 10 Stas Sergeev 2013-11-26 08:46:30 UTC
Thanks for CCing me the e-mail.
It recalled me another part of the solution,
which is the bug 55981.
It solves an opposite case: when icanon is
_disabled_ after some data was written but
no newline yet, the reader should be woken
up so the data to became immediately
available for read() in raw mode.
This is what patch 55981 does.
Comment 11 Alan 2014-01-20 16:58:40 UTC
Can we close these as obsolete now the code has been reworked upstream ?
Comment 12 Stas Sergeev 2014-01-20 19:12:39 UTC
The patch was modified and applied:
https://groups.google.com/forum/#!msg/linux.kernel/05c-vQUDww4/umXJsD_uiskJ
So this is a CODE_FIX.
Would be nice to get some attention to
other tty patches of mine too.

Note You need to log in before you can comment on or make changes to this bug.