Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 9 Apr 2003 15:49:14 +0400
From:      Yar Tikhiy <yar@freebsd.org>
To:        Bruce Evans <bde@zeta.org.au>
Cc:        arch@freebsd.org
Subject:   Re: termios & non-blocking I/O
Message-ID:  <20030409114914.GB63770@comp.chem.msu.su>
In-Reply-To: <20030409044301.J628@gamplex.bde.org>
References:  <20030408164614.GA7236@comp.chem.msu.su> <20030409044301.J628@gamplex.bde.org>

next in thread | previous in thread | raw e-mail | index | archive | help
On Wed, Apr 09, 2003 at 05:33:28AM +1000, Bruce Evans wrote:
> On Tue, 8 Apr 2003, Yar Tikhiy wrote:
> 
> > ...
> > Let's consider a non-blocking file descriptor that correspons to a
> > terminal in raw mode.  Let's also assume read(2) is issued on it
> > when there is no data to read.
> >
> > If for this terminal MIN > 0 and TIME == 0, read(2) will return -1
> > and set errno to EAGAIN.
> >
> > OTOH, if MIN == 0 and TIME > 0, read(2) will return 0.
> >
> > While not in disagreement with POSIX[1], such a behaviour has at
> > least one unwelcome consequence:  If a program has been compiled
> > with ``-pthread'', the TIME counter won't work on terminal descriptors
> > that are in blocking mode from the program's point of view -- read(2)
> > will instantly return 0 on them.  That is because the following
> > scenario will happen:
> 
> The spec is not very clear, but I think it means to say to return
> -1/EAGAIN (it says that first).

As far as I can understand, the spec says both 0 and -1/EAGAIN are
valid return values.  So it's up to us to decide which way is better.

> ...
> > 1) libc_r sets non-blocking mode on a descriptor as soon as a device
> > is opened (that is how i/o in user-land threads work);
> > 2) the program sets the TIME counter through tcsetattr(3);
> > 3) the program issues read(2), which ends up in the actual read()
> > syscall, which in turn returns 0 to libc_r (assuming there is no
> > data to read);
> > 4) libc_r thinks this is the EOF indicator, so it instantly returns
> > 0 to the program;
> > 5) the program breaks.
> >
> > Notice, that MIN works right with libc_r since read() syscall will
> > return -1/EAGAIN, which is correctly understood by libc_r: it will
> > block the current thread until there is data to read.
> 
> Does it keep the fd in non-blocking mode and wait for the data using
> select() or similar?

Yes, libc_r does read() on the fd and if the read() returns -1/EAGAIN,
it does poll() on the fd (as can be seen with ktrace.)

> This wouldn't work so well for TIME because
> select() doesn't really understand MIN/TIME; in particular, TIME
> has no effect on select() in the MIN == 0 && TIME > 0 case.  I
> think libc_r would have to duplicate most of the kernel's MIN/TIME
> stuff to fake things properly.  It correctly doesn't go near this.

Hmmm, it is a serious complication.  Shame on me that I have
overlooked it.  But that doesn't seem to keep us from making the
MIN and TIME cases consistent WRT the return values for non-blocking
fd's, does it?

-- 
Yar



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20030409114914.GB63770>