linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [BUG] drivers/tty: read() on a noncanonical blocking tty randomly fails when VMIN > received >= buf
@ 2016-05-04 23:00 Julio Guerra
  2016-05-04 23:07 ` Peter Hurley
  0 siblings, 1 reply; 6+ messages in thread
From: Julio Guerra @ 2016-05-04 23:00 UTC (permalink / raw)
  To: Peter Hurley <peter@hurleysoftware.com>; Greg Kroah-Hartman
  Cc: linux-kernel

Hi,

When a tty (here a slave pty) is set in noncanonical input and blocking 
read modes, a read() randomly blocks when:
"VMIN > kernel received >= user buffer size > 0".

The standard says that read() should block until VMIN bytes are received 
[1][2]. Whether this is an implementation defined case not really 
specified by POSIX or not, it should not behave randomly (otherwise it 
really should be documented in termios manpage).

I isolated it in the following example (with VMIN = 5, received = 4, 
user buffer = 3):
https://gist.github.com/Julio-Guerra/b3fdefab281403073607d81cabcea04a

Since it is random, you will need run it several times to observe both 
cases. When correctly behaving, it should block in the read() for ever 
(C-c to kill it). When incorrectly behaving, it does not block and reads 
into the user buffer what is present in the kernel receive buffer 
(string "any").

Example where it does not block 3 times out of 4:
  > $ ./a.out
  > res=3 buf=any
  > $ ./a.out
  > res=3 buf=any
  > $ ./a.out
  > ^C⏎

Linux version 4.5.1-1-ARCH (builduser@tobias) (gcc version 5.3.0 (GCC) ) 
#1 SMP PREEMPT Thu Apr 14 19:19:32 CEST 2016

[1] "Canonical and noncanonical mode", man termios
[2] 
http://www.gnu.org/software/libc/manual/html_node/Noncanonical-Input.html

-- 
Julio Guerra

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [BUG] drivers/tty: read() on a noncanonical blocking tty randomly fails when VMIN > received >= buf
  2016-05-04 23:00 [BUG] drivers/tty: read() on a noncanonical blocking tty randomly fails when VMIN > received >= buf Julio Guerra
@ 2016-05-04 23:07 ` Peter Hurley
  2016-05-04 23:27   ` Julio Guerra
  2016-05-05 10:08   ` One Thousand Gnomes
  0 siblings, 2 replies; 6+ messages in thread
From: Peter Hurley @ 2016-05-04 23:07 UTC (permalink / raw)
  To: Julio Guerra,
	Peter Hurley <peter@hurleysoftware.com>; Greg
	Kroah-Hartman
  Cc: linux-kernel

Hi Julio,

On 05/04/2016 04:00 PM, Julio Guerra wrote:
> Hi,
> 
> When a tty (here a slave pty) is set in noncanonical input and blocking read modes, a read() randomly blocks when:
> "VMIN > kernel received >= user buffer size > 0".
> 
> The standard says that read() should block until VMIN bytes are received [1][2]. Whether this is an implementation defined case not really specified by POSIX or not, it should not behave randomly (otherwise it really should be documented in termios manpage).

This is not a bug.

>From the termios(3) man page:

       * MIN > 0; TIME == 0: read(2) blocks until the lesser of MIN bytes or the number of bytes requested are avail‐
         able, and returns the lesser of these two values.

Regards,
Peter Hurley


> I isolated it in the following example (with VMIN = 5, received = 4, user buffer = 3):
> https://gist.github.com/Julio-Guerra/b3fdefab281403073607d81cabcea04a
> 
> Since it is random, you will need run it several times to observe both cases. When correctly behaving, it should block in the read() for ever (C-c to kill it). When incorrectly behaving, it does not block and reads into the user buffer what is present in the kernel receive buffer (string "any").
> 
> Example where it does not block 3 times out of 4:
>  > $ ./a.out
>  > res=3 buf=any
>  > $ ./a.out
>  > res=3 buf=any
>  > $ ./a.out
>  > ^C⏎
> 
> Linux version 4.5.1-1-ARCH (builduser@tobias) (gcc version 5.3.0 (GCC) ) #1 SMP PREEMPT Thu Apr 14 19:19:32 CEST 2016
> 
> [1] "Canonical and noncanonical mode", man termios
> [2] http://www.gnu.org/software/libc/manual/html_node/Noncanonical-Input.html
> 

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [BUG] drivers/tty: read() on a noncanonical blocking tty randomly fails when VMIN > received >= buf
  2016-05-04 23:07 ` Peter Hurley
@ 2016-05-04 23:27   ` Julio Guerra
  2016-05-05  0:50     ` Peter Hurley
  2016-05-05 10:08   ` One Thousand Gnomes
  1 sibling, 1 reply; 6+ messages in thread
From: Julio Guerra @ 2016-05-04 23:27 UTC (permalink / raw)
  To: Peter Hurley; +Cc: linux-serial, linux-kernel

>> When a tty (here a slave pty) is set in noncanonical input and blocking read modes, a read() randomly blocks when:
>> "VMIN > kernel received >= user buffer size > 0".
>>
>> The standard says that read() should block until VMIN bytes are received [1][2]. Whether this is an implementation defined case not really specified by POSIX or not, it should not behave randomly (otherwise it really should be documented in termios manpage).
>
> This is not a bug.
>
> From the termios(3) man page:
>
>        * MIN > 0; TIME == 0: read(2) blocks until the lesser of MIN bytes or the number of bytes requested are avail‐
>          able, and returns the lesser of these two values.
>

This does not appear in my man...

Anyway, how do you explain the random behavior then?

-- 
Julio Guerra

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [BUG] drivers/tty: read() on a noncanonical blocking tty randomly fails when VMIN > received >= buf
  2016-05-04 23:27   ` Julio Guerra
@ 2016-05-05  0:50     ` Peter Hurley
  0 siblings, 0 replies; 6+ messages in thread
From: Peter Hurley @ 2016-05-05  0:50 UTC (permalink / raw)
  To: Julio Guerra; +Cc: linux-serial, linux-kernel

On 05/04/2016 04:27 PM, Julio Guerra wrote:
>>> When a tty (here a slave pty) is set in noncanonical input and blocking read modes, a read() randomly blocks when:
>>> "VMIN > kernel received >= user buffer size > 0".
>>>
>>> The standard says that read() should block until VMIN bytes are received [1][2]. Whether this is an implementation defined case not really specified by POSIX or not, it should not behave randomly (otherwise it really should be documented in termios manpage).
>>
>> This is not a bug.
>>
>> From the termios(3) man page:
>>
>>        * MIN > 0; TIME == 0: read(2) blocks until the lesser of MIN bytes or the number of bytes requested are avail‐
>>          able, and returns the lesser of these two values.
>>
> 
> This does not appear in my man...
> 
> Anyway, how do you explain the random behavior then?

A long standing bug in this read mode allows the asynchronous input
processing thread to race with the read() thread and become confused
about how much data remains.

I fixed this in 4.6; when I run your test on 4.6, it consistently
returns the full user buffer.

Regards,
Peter Hurley

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [BUG] drivers/tty: read() on a noncanonical blocking tty randomly fails when VMIN > received >= buf
  2016-05-04 23:07 ` Peter Hurley
  2016-05-04 23:27   ` Julio Guerra
@ 2016-05-05 10:08   ` One Thousand Gnomes
  2016-05-05 15:28     ` Peter Hurley
  1 sibling, 1 reply; 6+ messages in thread
From: One Thousand Gnomes @ 2016-05-05 10:08 UTC (permalink / raw)
  To: Peter Hurley
  Cc: Julio Guerra,
	Peter Hurley <peter@hurleysoftware.com>; Greg
	Kroah-Hartman, linux-kernel

On Wed, 4 May 2016 16:07:44 -0700
Peter Hurley <peter@hurleysoftware.com> wrote:

> Hi Julio,
> 
> On 05/04/2016 04:00 PM, Julio Guerra wrote:
> > Hi,
> > 
> > When a tty (here a slave pty) is set in noncanonical input and blocking read modes, a read() randomly blocks when:
> > "VMIN > kernel received >= user buffer size > 0".
> > 
> > The standard says that read() should block until VMIN bytes are received [1][2]. Whether this is an implementation defined case not really specified by POSIX or not, it should not behave randomly (otherwise it really should be documented in termios manpage).  
> 
> This is not a bug.
> 
> >From the termios(3) man page:  
> 
>        * MIN > 0; TIME == 0: read(2) blocks until the lesser of MIN bytes or the number of bytes requested are avail‐
>          able, and returns the lesser of these two values.

The standard says

	Case B: MIN>0, TIME=0

	In case B, since the value of TIME is zero, the timer plays no
	role and only MIN is significant. A pending read shall not be
	satisfied until MIN bytes are received (that is, the pending read
	shall block until MIN bytes are received), or a signal is
	received. A program that uses case B to read record-based
	terminal I/O may block indefinitely in the read operation.

That is if you do 


	read(fd, buf, 3)

and MIN is 5, the read should not return until there are 5 bytes in the
queue. The following code is guaranteed to work reliably by the standard
with TIME 0 MIN 5 (ignoring signals for the moment)


	read(fd, buf, 3);
	fcntl(fd, F_SETFL, FNDELAY);
	assert(read(fd, buf, 2) == 2);

Historically this behaviour was useful for things like block transfer
protocols, especially with offloaded serial processing.

So actually I think we do have a bug, the behaviuour is not standards
compliant, and the man page documents the erroneous behaviour.

Alan

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [BUG] drivers/tty: read() on a noncanonical blocking tty randomly fails when VMIN > received >= buf
  2016-05-05 10:08   ` One Thousand Gnomes
@ 2016-05-05 15:28     ` Peter Hurley
  0 siblings, 0 replies; 6+ messages in thread
From: Peter Hurley @ 2016-05-05 15:28 UTC (permalink / raw)
  To: One Thousand Gnomes, Julio Guerra
  Cc: Peter Hurley <peter@hurleysoftware.com>; Greg
	Kroah-Hartman, linux-kernel

On 05/05/2016 03:08 AM, One Thousand Gnomes wrote:
> On Wed, 4 May 2016 16:07:44 -0700
> Peter Hurley <peter@hurleysoftware.com> wrote:
> 
>> Hi Julio,
>>
>> On 05/04/2016 04:00 PM, Julio Guerra wrote:
>>> Hi,
>>>
>>> When a tty (here a slave pty) is set in noncanonical input and blocking read modes, a read() randomly blocks when:
>>> "VMIN > kernel received >= user buffer size > 0".
>>>
>>> The standard says that read() should block until VMIN bytes are received [1][2]. Whether this is an implementation defined case not really specified by POSIX or not, it should not behave randomly (otherwise it really should be documented in termios manpage).  
>>
>> This is not a bug.
>>
>> >From the termios(3) man page:  
>>
>>        * MIN > 0; TIME == 0: read(2) blocks until the lesser of MIN bytes or the number of bytes requested are avail‐
>>          able, and returns the lesser of these two values.
> 
> The standard says
> 
> 	Case B: MIN>0, TIME=0
> 
> 	In case B, since the value of TIME is zero, the timer plays no
> 	role and only MIN is significant. A pending read shall not be
> 	satisfied until MIN bytes are received (that is, the pending read
> 	shall block until MIN bytes are received), or a signal is
> 	received. A program that uses case B to read record-based
> 	terminal I/O may block indefinitely in the read operation.
> 
> That is if you do 
> 
> 
> 	read(fd, buf, 3)
> 
> and MIN is 5, the read should not return until there are 5 bytes in the
> queue. The following code is guaranteed to work reliably by the standard
> with TIME 0 MIN 5 (ignoring signals for the moment)
> 
> 
> 	read(fd, buf, 3);
> 	fcntl(fd, F_SETFL, FNDELAY);
> 	assert(read(fd, buf, 2) == 2);
> 
> Historically this behaviour was useful for things like block transfer
> protocols, especially with offloaded serial processing.
> 
> So actually I think we do have a bug, the behaviuour is not standards
> compliant, and the man page documents the erroneous behaviour.

I disagree; I think SUSv4 fails to address this degenerate condition at all.
For example, SUSv4 specifically states that there is no precedence of
MIN/TIME with O_NONBLOCK. IOW, the standard does _not_ guarantee that your
code fragment above won't block on the subsequent read anyway since it fails
to meet the new MIN 5 watermark.

But I have no problem fixing a bona fide regression; what's broken?

^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2016-05-05 15:28 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-05-04 23:00 [BUG] drivers/tty: read() on a noncanonical blocking tty randomly fails when VMIN > received >= buf Julio Guerra
2016-05-04 23:07 ` Peter Hurley
2016-05-04 23:27   ` Julio Guerra
2016-05-05  0:50     ` Peter Hurley
2016-05-05 10:08   ` One Thousand Gnomes
2016-05-05 15:28     ` Peter Hurley

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).