Skip site navigation (1)Skip section navigation (2)
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>