Question

I have an FTDI USB serial device which I use via the termios serial API. I set up the port so that it will time-out on read() calls in half a second (by using the VTIME parameter), and this works on Linux as well as on FreeBSD. On OpenBSD 5.1, however, the read() call simply blocks forever when no data is available (see below.) I would expect read() to return 0 after 500ms.

Can anyone think of a reason that the termios API would behave differently under OpenBSD, at least with respect to the timeout feature?

EDIT: The no-timeout problem is caused by linking against pthread. Regardless of whether I'm actually using any pthreads, mutexes, etc., simply linking against that library causes read() to block forever instead of timing out based on the VTIME setting. Again, this problem only manifests on OpenBSD -- Linux and FreeBSD work as expected.

if ((sd = open(devPath, O_RDWR | O_NOCTTY)) >= 0)
{
  struct termios newtio;
  char input;

  memset(&newtio, 0, sizeof(newtio));

  // set options, including non-canonical mode
  newtio.c_cflag = (CREAD | CS8 | CLOCAL);
  newtio.c_lflag = 0;

  // when waiting for responses, wait until we haven't received
  // any characters for 0.5 seconds before timing out
  newtio.c_cc[VTIME] = 5;
  newtio.c_cc[VMIN] = 0;

  // set the input and output baud rates to 7812
  cfsetispeed(&newtio, 7812);
  cfsetospeed(&newtio, 7812);

  if ((tcflush(sd, TCIFLUSH) == 0) &&
      (tcsetattr(sd, TCSANOW, &newtio) == 0))
  {
    read(sd, &input, 1); // even though VTIME is set on the device,
                         // this read() will block forever when no
                         // character is available in the Rx buffer
  }
}
Était-ce utile?

La solution

from the termios manpage:

 Another dependency is whether the O_NONBLOCK flag is set by open() or
 fcntl().  If the O_NONBLOCK flag is clear, then the read request is
 blocked until data is available or a signal has been received.  If the
 O_NONBLOCK flag is set, then the read request is completed, without
 blocking, in one of three ways:

       1.   If there is enough data available to satisfy the entire
            request, and the read completes successfully the number of
            bytes read is returned.

       2.   If there is not enough data available to satisfy the entire
            request, and the read completes successfully, having read as
            much data as possible, the number of bytes read is returned.

       3.   If there is no data available, the read returns -1, with errno
            set to EAGAIN.

can you check if this is the case? cheers.

Edit: OP traced back the problem to a linking with pthreads that caused the read function to block. By upgrading to OpenBSD >5.2 this issue was resolved by the change to the new rthreads implementation as the default threading library on openbsd. more info on guenther@ EuroBSD2012 slides

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top