* [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