C++ select() not waiting for timeout period

半腔热情 提交于 2019-12-22 08:26:03

问题


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;
}

回答1:


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.




回答2:


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;
}



回答3:


If you ever read the source of select.c in linux kernel, you'll find that in the select() call, the last parameter timeout will be set to zero after it is used.

So, you should set the value of tv inside the loop, before each call of select().




回答4:


If memory serves, the call to select() can change the value of tv to indicate the time remaining. You should reinitialize tv before each call to select().




回答5:


You must put

FD_ZERO(&readfds);
FD_SET(STDIN, &readfds);

into your loop. Assigning: readfds = master; will not always work (actually I'm pretty sure it will not work in every platform - depending on the definition of fd_et). also setting tv in a loop is a good idea.



来源:https://stackoverflow.com/questions/9494626/c-select-not-waiting-for-timeout-period

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!