C ++ select () does not wait for a timeout

I try to use the select function to accept input, but every 2 seconds does something else if the user hasn’t added anything. The code below waits two seconds when the first time () is selected, but after it prints the first message "timeout", it quickly continues to "log out", without waiting for 2 seconds, basically entering into an infinite loop. Does 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; } 
+4
source share
5 answers

per person: select () can update the timeout argument to indicate how much time is left. pselect () does not change this argument.

This means that if it expires after 2 seconds, it can set your tv_sec to 0.

If both timeval fields are 0, it will immediately return.

Try setting a timeout in each loop inside while () to ensure that it will not be overwritten.

+11
source

I am making some changes based on your code after select tv is 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; } 
+2
source

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

So, before each select () call, you must set the tv value in the loop.

+1
source

If memory is used, calling select() may change the tv value to indicate the remaining time. You must reinitialize tv before each select() call.

+1
source

You have to put

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

into your cycle. Purpose: readfds = master; will not always work (in fact, I am sure that it will not work on every platform - depending on the definition of fd_et ). also setting tv in a loop is a good idea.

+1
source

Source: https://habr.com/ru/post/1398959/


All Articles