Re: mixing O_NONBLOCK and raw tty causes portability problems

[email protected] (Niels Möller)
Newsgroups gmane.network.lsh.bugs
Message-ID <[email protected]>
Matthias Drochner <[email protected]> writes:

> [email protected] said:
> > I rely on the following behaviour of VMIN > 0 and VTIME > 0, as
> > described by the glibc manual: 
> > [...]
> >      `read' always blocks until the first character arrives
> 
> This obviously refers to the !O_NONBLOCK case...

Sure. I find it very unfortunate that the tty flags and the non-block
flags aren't orthogonal.

> - If O_NONBLOCK, we can't sleep.

Obviously, with O_NONBLOCK, read should not sleep. That's the point of
O_NONBLOCK. 

> - A tty file descriptor might not be considered "readable" unless it
>   fulfills the VMIN/VTIME conditions. Now there are some pitfalls:
>   - a VTIME timeout begins at the time the read() call is done,

Sure about that? I believe the timer should be started as soon as a
character arrives to the tty driver, regardless of what system calls
are made. That's also the way I read the spec you point to:

  "In this case TIME serves as an inter-byte timer and is activated
   after the first byte is received. Since it is an inter-byte timer,
   it is reset after a byte is received."

In this context, I think "received" must mean that bytes arrive to the
tty driver (via a the serial line or whatever).

>   - also, the result of poll()/select() must not depend on setting
>     of O_NONBLOCK (stated in some standard, maybe I'll find it...)

Makes sense, too bad posix seems to not require this to be true for
tty:s.

>   - What does "readable" mean? "will return immediately with data"
>     or "will not block indefinitely"?

To me, "readable" mean that a plain vanilla ordinary blocking read on
the fd would return immediately, with success (i.e. with data or an
EOF indication) without putting my process to sleep. If a blocking
read wouldn't return immediately due to the VTIME value, then the fd
is *not* readable.

> - One could assume: If a read() returns with less than VMIN chars,
>   there was a gap of at least VTIME after the last. This might hold
>   in presence of O_NONBLOCK or not...

Don't understand the relevance of this.

> > On netbsd, if you type quickly, will read return several characters at
> > a time?
> 
> I can't type quick enough to get more characters between the poll()
> and the read().

And it doesn't matter if you increasing VTIME, I guess?

> Hmm - this is one of the gray areas... if there is a O_NONBLOCK,
> should the VTIME have an effect at all?

Well, that's what you keep saying. I think the Solaris behaviour here
makes perfect sense. The VMIN/VTIME are orthogonal to O_NONBLOCK, you
can use one or the other, or both, and in all cases get sane
behaviour. Linux and netbsd are appearantly broken (although still
posix compliant on this issue), the question for lsh is how to best
work around it.

> http://www.opengroup.org/onlinepubs/007908799/xbd/termios.html
> The sentence I was referring to is in the "Non-canonical Mode Input
> Processing" chapter, beginning
> "The ISO POSIX-1 standard does not specify".

Thanks. This section says:

  The ISO POSIX-1 standard does not specify whether the setting of
  O_NONBLOCK takes precedence over MIN or TIME settings. 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].

The second sentence says that the kernel can return immedately,
without violating POSIX. The third says that the kernel can return
immedately, *with 0 as a return value*.

*BLECH*

That basically means that an operating system can be perfectly posix
compliant, without implementing a useful O_NONBLOCK at all (instead,
O_NONBLOCK can be an alias for the older, totally braindead, O_NDELAY
flag).

> select() is older and supported on more systems, agreed. Nowadays I'd
> assume that poll() works on every system I'd consider worth working
> with...

Well, poll works on both linux and Solaris, but the way they set the
various poll flags is very different. Don't know any details bsd's
poll.

> (My failure report wasn't very precise, sorry. Actually, I didn't get
> just a single "EWOULDBLOCK" message after a keystroke, but lsh went into
> an endless loop printing these messages after I pressed a key.)

That's worse, then just ignoring the error is not an option.

Exactly which version of netbsd are you using?

Regards,
/Niels

PS. I think the O_NONBLOCK flag is a really bad design. I really wish
    kernel hackers would consider adding non-blocking syscalls like
    nonblock_read and nonblock_write, as suggested by djb at
    http://cr.yp.to/unix/nonblock.html).
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.