Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > linux.kernel > #1394778 > unrolled thread

Re: [BUG] drivers/tty: read() on a noncanonical blocking tty randomly fails when VMIN > received >= buf

Started byPeter Hurley <peter@hurleysoftware.com>
First post2016-05-05 01:10 +0200
Last post2016-05-05 17:30 +0200
Articles 5 — 3 participants

Back to article view | Back to linux.kernel

This discussion starts older than the indexed window; earlier articles aren't shown. The article labeled Started by below is the oldest one visible, not the original post.


Contents

  Re: [BUG] drivers/tty: read() on a noncanonical blocking tty randomly  fails when VMIN > received >= buf Peter Hurley <peter@hurleysoftware.com> - 2016-05-05 01:10 +0200
    Re: [BUG] drivers/tty: read() on a noncanonical blocking tty randomly  fails when VMIN > received >= buf Julio Guerra <julio@farjump.io> - 2016-05-05 01:30 +0200
      Re: [BUG] drivers/tty: read() on a noncanonical blocking tty randomly  fails when VMIN > received >= buf Peter Hurley <peter@hurleysoftware.com> - 2016-05-05 03:00 +0200
    Re: [BUG] drivers/tty: read() on a noncanonical blocking tty  randomly fails when VMIN > received >= buf One Thousand Gnomes <gnomes@lxorguk.ukuu.org.uk> - 2016-05-05 12:10 +0200
      Re: [BUG] drivers/tty: read() on a noncanonical blocking tty randomly  fails when VMIN > received >= buf Peter Hurley <peter@hurleysoftware.com> - 2016-05-05 17:30 +0200

#1394778 — Re: [BUG] drivers/tty: read() on a noncanonical blocking tty randomly fails when VMIN > received >= buf

FromPeter Hurley <peter@hurleysoftware.com>
Date2016-05-05 01:10 +0200
SubjectRe: [BUG] drivers/tty: read() on a noncanonical blocking tty randomly fails when VMIN > received >= buf
Message-ID<rve5A-4JL-13@gated-at.bofh.it>
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
> 

[toc] | [next] | [standalone]


#1394786

FromJulio Guerra <julio@farjump.io>
Date2016-05-05 01:30 +0200
Message-ID<rveoW-4Yr-19@gated-at.bofh.it>
In reply to#1394778
>> 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

[toc] | [prev] | [next] | [standalone]


#1394812

FromPeter Hurley <peter@hurleysoftware.com>
Date2016-05-05 03:00 +0200
Message-ID<rvfO2-6ep-5@gated-at.bofh.it>
In reply to#1394786
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

[toc] | [prev] | [next] | [standalone]


#1395015 — Re: [BUG] drivers/tty: read() on a noncanonical blocking tty randomly fails when VMIN > received >= buf

FromOne Thousand Gnomes <gnomes@lxorguk.ukuu.org.uk>
Date2016-05-05 12:10 +0200
SubjectRe: [BUG] drivers/tty: read() on a noncanonical blocking tty randomly fails when VMIN > received >= buf
Message-ID<rvooi-6rF-17@gated-at.bofh.it>
In reply to#1394778
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

[toc] | [prev] | [next] | [standalone]


#1395182

FromPeter Hurley <peter@hurleysoftware.com>
Date2016-05-05 17:30 +0200
Message-ID<rvtnX-2lG-3@gated-at.bofh.it>
In reply to#1395015
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?

[toc] | [prev] | [standalone]


Back to top | Article view | linux.kernel


csiph-web