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>