linux-serial.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: "Michael Kerrisk (man-pages)" <mtk.manpages@gmail.com>
To: Peter Hurley <peter@hurleysoftware.com>
Cc: mtk.manpages@gmail.com,
	linux kernel <linux-kernel@vger.kernel.org>,
	linux-serial <linux-serial@vger.kernel.org>,
	One Thousand Gnomes <gnomes@lxorguk.ukuu.org.uk>,
	Ivan <athlon_@mail.ru>
Subject: Re: man termios
Date: Fri, 21 Mar 2014 14:15:27 +0100	[thread overview]
Message-ID: <532C3B6F.2000300@gmail.com> (raw)
In-Reply-To: <532C20B7.2070806@hurleysoftware.com>

[-- Attachment #1: Type: text/plain, Size: 6221 bytes --]

On 03/21/2014 12:21 PM, Peter Hurley wrote:
> On 03/21/2014 06:45 AM, Michael Kerrisk (man-pages) wrote:
>>> This is also true of the other non-canonical
>>> read()'s with timeout (TIME > 0).
>>
>> Here, if I understand you correctly, you mean this case:
>> * TIME > 0
>> * MIN == 0
>> * O_NONBLOCK set on the FD
>> * No input available
>>
>> You are saying that read() returns 0 in this case? This doesn't appear
>> to me to be correct (on Linux). How did you verify this?
> 
> Apologies, my mistake here.

Okay -- thanks for confirming.

> (aside: O_NONBLOCK can be changed while the reader is blocked, but that's
> not what I meant originally, and I wouldn't document it there)
> 
>>> 'man termios' is silent here, but 62.6.2 in LPI implies that O_NONBLOCK will
>>> return -1 with errno==EAGAIN; it does not.
>>
>> I guess you are referring to this text in TLPI:
> 
> Yes.
> 
>> [[
>> This mode is somewhat similar to setting the O_NONBLOCK flag for the
>> terminal (Section 5.9). However, with O_NONBLOCK, if no bytes are
>> available for reading, then read() returns –1 with the error
>> EAGAIN.
>> ]]
>>
>> Oops. The text was not meant to imply that. Rather the comparison was
>> intended to be with O_NONBLOCK *in canonical mode*. However, I agree
>> that I could have made that more explicit. (I'll add an erratum to
>> mention canonical mode.)
>>
>>> This is unspecified by POSIX (11.1.7).
>>
>> Yep, I see. XBD 11.1.7 says:
>>
>> [[
>> Therefore, if O_NONBLOCK is set, read( ) may return immediately,
>> regardless of the setting of MIN or TIME. Also, if no data is
>> available, read( ) may either return 0, or return -1 with errno set to
>> [EAGAIN].
>> ]]
>>
>> So, it seems to be saying that either behavior is allowed, right?
> 
> Exactly.
> 
>> And as far as I can see, for the TIME>0 case on Linux, read() returns
>> -1 + EGAIN.
> 
> You're right about the TIME>0 case.
> 
>> In any case, I've added this text to termios(3):
>>
>>         POSIX  does  not  specify whether the setting of the O_NONBLOCK
>>         file status flag takes precedence over the MIN  and  TIME  set‐
>>         tings.  If O_NONBLOCK is set, a read() in noncanonical mode may
>>         return immediately, regardless of the setting of MIN  or  TIME.
>>         Furthermore, if no data is available, POSIX permits a read() in
>>         noncanonical mode to return either 0, or -1 with errno  set  to
>>         EAGAIN.
> 
> 
> Great; I think that will really help clarify the usage wrt O_NONBLOCK.

[...]

>>> Finally, if the 'count' parameter is less than MIN, read() may return before
>>> MIN bytes have been received, if 'count' bytes have been received.
>>
>> Yes. But it's not clear to me here: do you mean that something in the
>> man page (or in TLPI) needs fixing?
> 
> Well, what I mean here is that read() may also _not_ return until MIN bytes have
> been received, even if 'count' bytes have been received.

Ahh -- I see what you mean. And, it looks like there is a point here where Linux
differs from POSIX and (at least) Solaris. See the current man-page text below,
in particular the MIN>0, TIME>0 case. I've also attached a simple test program 
that I used, below.

       In noncanonical mode input is available immediately (without  the
       user  having  to  type a line-delimiter character), no input pro‐
       cessing is performed, and line editing is disabled.  The settings
       of  MIN (c_cc[VMIN]) and TIME (c_cc[VTIME]) determine the circum‐
       stances in which a read(2) completes;  there  are  four  distinct
       cases:

       MIN == 0; TIME == 0:
              If  data  is  available, read(2) returns immediately, with
              the lesser of the number of bytes available, or the number
              of  bytes  requested.   If  no  data is available, read(2)
              returns 0.

       MIN > 0; TIME == 0:
              read(2) blocks until MIN bytes are available, and  returns
              up to the number of bytes requested.

       MIN == 0; TIME > 0:
              TIME  specifies  the limit for a timer in tenths of a sec‐
              ond.   The  timer  is  started  when  read(2)  is  called.
              read(2)  returns  either when at least one byte of data is
              available, or  when  the  timer  expires.   If  the  timer
              expires  without  any  input  becoming  available, read(2)
              returns 0.  If data is already available at  the  time  of
              the call to read() the call behaves as though the data was
              received immediately after the call.

       MIN > 0; TIME > 0:
              TIME specifies the limit for a timer in tenths of  a  sec‐
              ond.  Once an initial byte of input becomes available, the
              timer is restarted after each further  byte  is  received.
              read(2)  returns  when  any of the following conditions is
              met:

              *  MIN bytes have been received.

              *  The interbyte timer expires.

              *  The number of  bytes  requested  by  read(2)  has  been
                 received.   (POSIX  does  not  specify this termination
                 condition, and on  some  other  implementations  read()
                 does not return in this case.)

              Because  the  timer is started only after the initial byte
              becomes available, at least one byte  will  be  read.   If
              data  is  already  available  at  the  time of the call to
              read() the call behaves as though the  data  was  received
              immediately after the call.

       POSIX does not specify whether the setting of the O_NONBLOCK file
       status flag takes precedence over the MIN and TIME settings.   If
       O_NONBLOCK is set, a read() in noncanonical mode may return imme‐
       diately, regardless of the setting of MIN or TIME.   Furthermore,
       if  no  data is available, POSIX permits a read() in noncanonical
       mode to return either 0, or -1 with errno set to EAGAIN.

Cheers,

Michael


-- 
Michael Kerrisk
Linux man-pages maintainer; http://www.kernel.org/doc/man-pages/
Linux/UNIX System Programming Training: http://man7.org/training/

[-- Attachment #2: noncanonical.c --]
[-- Type: text/x-csrc, Size: 1443 bytes --]

/*#* noncanonical.c

   Usage: see below.
*/
#include <termios.h>
#include <signal.h>
#include <fcntl.h>
#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>

#define errExit(msg) 	do { perror(msg); exit(EXIT_FAILURE); \
			} while (0)


int
main(int argc, char *argv[])
{
    char buf[100000];
    struct termios tp;
    ssize_t numRead;
    int sleepTime;

    if (argc < 4) {
	fprintf(stderr, "Usage: %s TIME MIN num-bytes-to-read "
		"[sleep-secs [O_NONBLOCK flag]]\n", argv[0]);
	exit(EXIT_FAILURE);
    }

    if (tcgetattr(STDIN_FILENO, &tp) == -1)
	errExit("tcgetattr");

    tp.c_lflag &= ~ICANON;
    tp.c_cc[VTIME] = atoi(argv[1]);
    tp.c_cc[VMIN] = atoi(argv[2]);

    if (tcsetattr(STDIN_FILENO, TCSANOW, &tp) == -1)
        errExit("tcsetattr");

    if (argc > 5) {
	int flags;

	flags = fcntl(STDIN_FILENO, F_GETFL);
	if (flags == -1)
	    errExit("fcntl");
	flags |= O_NONBLOCK;
	if (fcntl(STDIN_FILENO, F_SETFL, flags) == -1)
	    errExit("fcntl");
    }

    sleepTime = (argc > 4) ? atoi(argv[4]) : 5;
    printf("About to sleep for %d seconds\n", sleepTime);
    sleep(sleepTime);
    printf("Done sleeping\n");

    printf("About to read %d bytes\n", atoi(argv[3]));
    numRead = read(STDIN_FILENO, buf, atoi(argv[3]));
    if (numRead == -1)
	errExit("read");
    printf("read returned %ld\n", (long) numRead);

    exit(EXIT_SUCCESS);
} /* main */

  reply	other threads:[~2014-03-21 13:15 UTC|newest]

Thread overview: 10+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-03-20 18:42 man termios Peter Hurley
2014-03-21 10:45 ` Michael Kerrisk (man-pages)
2014-03-21 11:21   ` Peter Hurley
2014-03-21 13:15     ` Michael Kerrisk (man-pages) [this message]
2014-03-21 14:03       ` Peter Hurley
2014-03-21 14:17         ` Michael Kerrisk (man-pages)
2014-03-21 14:51           ` Peter Hurley
2014-03-21 15:41             ` Michael Kerrisk (man-pages)
2014-03-21 16:11               ` Peter Hurley
2014-03-21 18:45                 ` Michael Kerrisk (man-pages)

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=532C3B6F.2000300@gmail.com \
    --to=mtk.manpages@gmail.com \
    --cc=athlon_@mail.ru \
    --cc=gnomes@lxorguk.ukuu.org.uk \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-serial@vger.kernel.org \
    --cc=peter@hurleysoftware.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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).