From owner-freebsd-hackers Tue Jan 14 09:47:51 1997 Return-Path: Received: (from root@localhost) by freefall.freebsd.org (8.8.4/8.8.4) id JAA25811 for hackers-outgoing; Tue, 14 Jan 1997 09:47:51 -0800 (PST) Received: from cold.org (glacier.cold.org [206.81.134.54]) by freefall.freebsd.org (8.8.4/8.8.4) with ESMTP id JAA25806 for ; Tue, 14 Jan 1997 09:47:49 -0800 (PST) Received: from localhost (brandon@localhost) by cold.org (8.8.3/8.8.3) with SMTP id KAA03253 for ; Tue, 14 Jan 1997 10:48:47 -0700 (MST) Date: Tue, 14 Jan 1997 10:48:47 -0700 (MST) From: Brandon Gillespie To: freebsd-hackers@freeBSD.org Subject: select() on a serial device--ignoring OS buffered chars? Message-ID: MIME-Version: 1.0 Content-Type: TEXT/PLAIN; charset=US-ASCII Sender: owner-hackers@freeBSD.org X-Loop: FreeBSD.org Precedence: bulk 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