select() times out even though there is data in the buffer

183 Views Asked by At

This program is (I believe) a straight application of select() (on Debian for ARM). XBEEDEVICE points to a serial port. The serial port exists and ic connected to a device.

Problem is, select() returns 0 even though there is data received. I temporarily commented out the last 'else' and the program prints TIMEOUT, then the string that was returned by the remote device.

int main( int argc, char **argv ) {
  int fd, c, res, n;
  struct termios oldtio, newtio;
  char buf[255] = {0};

  fd_set input;
  struct timeval timeout;

  // define timeout
  timeout.tv_sec = 5;
  timeout.tv_usec = 0;

  fd = open( XBEEDEVICE, O_RDWR | O_NOCTTY );
  if( fd < 0 ){
    perror( XBEEDEVICE );
    return( -1 );
  }

  tcgetattr( fd, &oldtio ); /* save current port settings */
  bzero( &newtio, sizeof( newtio ));
  newtio.c_cflag = CRTSCTS | CS8 | CLOCAL | CREAD;
  newtio.c_iflag = IGNPAR;
  newtio.c_oflag = 0;

  /* set input mode (non-canonical, no echo,...) */
  newtio.c_lflag = 0;

  newtio.c_cc[VTIME]    = 0;   /* inter-character timer unused */
  newtio.c_cc[VMIN]     = 2;   /* blocking read until 2 chars received */

  tcflush( fd, TCIFLUSH );
  tcsetattr( fd, TCSANOW, &newtio );

  // Sending +++ within 1 second sets the XBee into command mode
  printf( " Sending +++\n" );
  write( fd, "+++", 3 );

  n = select( fd, &input, NULL, NULL, &timeout );

  if( n < 0 )
    printf( "select() failed\n" );
  else if( n == 0 )
    printf( "TIMEOUT\n" );
  //else{
    res = read( fd, buf, 250 );
    buf[res] = 0;
    printf( "Received: %s\n", buf );
  //}
  tcsetattr( fd, TCSANOW, &oldtio );

  return( 0 );
}
1

There are 1 best solutions below

2
n. m. could be an AI On

You should initialize input to contain fd. This is done with FD_ZERO and FD_SET macros:

FD_ZERO(&input);
FD_SET(fd, &input);

This must be done done each time before select is called.

The first argument to select should be fd+1. It is the number of file descriptors in the range to be checked. Since the maximal (and only) descriptor number in the range is fd, and the minimum is always 0, the number in question is fd+1.