Amir
Amir

Reputation: 11096

STDIN prevents activating of other file descriptors

The following program is written to receive clients' messages and read user inputs from keyboard:

FD_ZERO(&masterfds);
FD_SET(udp_con, &masterfds);
FD_SET(0, &masterfds);
maxfds = udp_con;
while(exit == false)
{ 
  FD_ZERO(&readfds);
  readfds = masterfds;

  selectFunc = select(maxfds+1, &readfds, NULL, NULL, &tv);
  if(selectFunc < 0) {
    message("error in select");
    exit = true;
  } else {
    // The server has received something from a client
    for(i = 0; i <= maxfds; i++) {
      if(FD_ISSET(i, &readfds)) {
        if(FD_ISSET(0, &readfds)) {
          fgets(userInput, sizeof(userInput), stdin);
          int len = strlen(userInput) - 1;
          if (userInput[len] == '\n') {
            userInput[len] = '\0';
          }
          cout<<"The user said: "<<userInput<<endl;
        } else if(i == udp_con) {
          cout<<"Datagram received"<<endl;
          // After reading the user input, it never reaches here
        }
      }
    }
  }
}

The problem is that when I press the 'enter' key on the keyboard and the '0' file descriptor activates, the program will never activate any other file descriptor and it locks on the '0' file descriptor. How can I fix this bug?

Upvotes: 0

Views: 163

Answers (1)

Adam Liss
Adam Liss

Reputation: 48290

You need to FD_CLR(0, readfds) after you test it with FD_ISSET(0, &readfds), or else it will always take that branch.

But you can simplify the algorithm by rewriting it. It's a good idea to get into the habit of formatting your code to make it easily readable.

FD_ZERO(&masterfds);
FD_SET(udp_con, &masterfds);
FD_SET(0, &masterfds);
maxfds = udp_con;

while (true) {
  readfds = masterfds;

  selectFunc = select(maxfds + 1, &readfds, NULL, NULL, &tv);
  if (selectFunc < 0) {
    message("error in select");
    break;
  }

  // Check for input on stdin (fd 0).
  if (FD_ISSET(0, &readfds)) {
    fgets(userInput, sizeof(userInput), stdin);
    int len = strlen(userInput) - 1;
    if (userInput[len] == '\n') {
      userInput[len] = '\0';
    }
    cout << "The user said: '" << userInput << "'" << endl;
  }
  // Check for input on the udp_con fd.
  if (FD_ISSET(udp_con, &readfds)) {
    cout << "Datagram received" << endl;
  }
}

Upvotes: 1

Related Questions