Date: Tue, 14 Jan 1997 10:48:47 -0700 (MST) From: Brandon Gillespie <brandon@cold.org> To: freebsd-hackers@freeBSD.org Subject: select() on a serial device--ignoring OS buffered chars? Message-ID: <Pine.NEB.3.95.970114104018.3232A-100000@cold.org>
next in thread | raw e-mail | index | archive | help
I have a function that does a read on a serial device that is set as
non-blocking. I have a monitor on the line and I KNOW the OS has the
characters sent to it, and they are likely buffered, but this function is
not behaving correctly. How DOES select() behave with a 'timeout' waiting
for input? I'm calling it with a 60 second timeout waiting for one
bleeding character--it reaches the end of the 60 seconds and says nothing
was received. The code is:
static Bool read_port_char(uChar * c, int sec, long usec) {
fd_set read_fds;
int r = 0;
int scount;
struct timeval tv;
if (!(r = read(portfd, c, 1))) {
/* use select to timeout */
FD_ZERO(&read_fds);
DEBUGMSG(("read char: sec=%d; usec=%d\n", sec, usec));
tv.tv_sec = sec*60;
tv.tv_usec = usec;
FD_SET(portfd, &read_fds);
scount = select(1, &read_fds, NULL, NULL, &tv);
/* crash and burn? */
if (scount == F_FAILURE && errno != EINTR) {
DEBUGMSG(("select(1, {%d,%ld}, NULL, NULL, &tv)\n",sec,usec));
die("read_port_char(): select(): [%d] %s\n",errno,strerror(errno));
}
/* anything happen, or did we just timeout? */
if (scount <= 0)
return NO;
/* if the count is one this should already be relevant, but *shrug* */
if (!FD_ISSET(portfd, &read_fds))
return NO;
/* we should never fail here--its only one char and select said yes */
if (!(r = read(portfd, c, 1)))
return NO;
}
if (r == F_FAILURE)
die("read(): %s\n", strerror(errno));
return YES;
}
If it gets a character on the first read it works fine. If it drops to
using select to timeout it never reads a character (it'll always return
NO). I know the input is there because after this timeout the code
calling it resets what it was doing and re-reads, immediately it gets a
character.
Notes: portfd is a /dev/tty device that has been open()ed as a
non-blocking device. I have done this hundred of other times in other
code--but never using select in this way. sec is either zero or one, I
multiply it by 60 to make the 'sleep' time visibly noticable.
Help? I can revert this code back to what it was before--where I called
the select with no file descriptors simply to get a microsecond sleep, but
I would prefer to use select as it was intended...
-Brandon Gillespie
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?Pine.NEB.3.95.970114104018.3232A-100000>
