Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++ select() not waiting for timeout period

I'm trying to use the select function to accept input but every 2 seconds do something else if the user hasn't entered anything. The code below is waiting two seconds the first time select() is reached but once it prints the first "timed out" message it rapidly keep printing out "timed out" without waiting for 2 seconds, basically entering an infinite loop. Anyone know what the problem is? Thanks for any help.

#include <stdio.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
using namespace std;

const int STDIN = 0;
int main(int argc, int *argv[])
{
struct timeval tv;
fd_set readfds, master;
tv.tv_sec = 2;
tv.tv_usec = 0;
FD_ZERO(&readfds);
FD_ZERO(&master);
FD_SET(STDIN, &readfds);
FD_SET(STDIN, &master);
string buffer = "";
while(buffer != "quit"){
    readfds = master;
    if(select(STDIN+1, &readfds, NULL, NULL, &tv) == -1) perror("select");
    if (FD_ISSET(STDIN, &readfds)){
        getline(cin, buffer);
        cout << "You entered: " << buffer << endl;
    }else
        cout << "Timed out.\n" << endl;
}
return 0;
}
like image 290
pandaEater Avatar asked Nov 30 '22 06:11

pandaEater


2 Answers

per man: select() may update the timeout argument to indicate how much time was left. pselect() does not change this argument.

This implies that if it times out after 2 seconds it could set your tv_sec to 0.

If both of the fields of timeval are 0 it will return immediately.

Try setting your timeout every loop inside the while() to insure it's not getting overwritten.

like image 130
Brett W Avatar answered Dec 04 '22 07:12

Brett W


I do some change based on your code, after select tv will be changed.

#include <stdio.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
#include <string.h>
#include <iostream>
using namespace std;

const int STDIN = 0;
int main(int argc, int *argv[])
{
        struct timeval tv,tv1;
        fd_set readfds, master;
        tv.tv_sec = 2;
        tv.tv_usec = 0;
        FD_ZERO(&readfds);
        FD_ZERO(&master);
        FD_SET(STDIN, &readfds);
        FD_SET(STDIN, &master);
        string buffer = "";
        while(buffer != "quit"){
                readfds = master;
                memcpy(&tv1, &tv, sizeof(tv));
                if(select(STDIN+1, &readfds, NULL, NULL, &tv1) == -1) perror("select");
                if (FD_ISSET(STDIN, &readfds)){
                        getline(cin, buffer);
                        cout << "You entered: " << buffer << endl;
                }else
                        cout << "Timed out.\n" << endl;
        }
        return 0;
}
like image 27
xda1001 Avatar answered Dec 04 '22 07:12

xda1001