I’m using select() in a thread to monitor a datagram socket, but unless data is being sent to the socket before the thread starts, select() will continue to return 0.
I’m mixing a little C and C++; here’s the method that starts the thread:
bool RelayStart() {
sock_recv = socket(AF_INET, SOCK_DGRAM, 0);
memset(&addr_recv, 0, sizeof(addr_recv));
addr_recv.sin_family = AF_INET;
addr_recv.sin_port = htons(18902);
addr_recv.sin_addr.s_addr = htonl(INADDR_ANY);
bind(sock_recv, (struct sockaddr*) &addr_recv, sizeof(addr_recv));
isRelayingPackets = true;
NSS::Thread::start(VIDEO_SEND_THREAD_ID);
return true;
}
The method that stops the thread:
bool RelayStop() {
isSendingVideo = false;
NSS::Thread::stop();
close(sock_recv);
return true;
}
And the method run in the thread:
void Run() {
fd_set read_fds;
int select_return;
struct timeval select_timeout;
FD_ZERO(&read_fds);
FD_SET(sock_recv, &read_fds);
while (isRelayingPackets) {
select_timeout.tv_sec = 1;
select_timeout.tv_usec = 0;
select_return = select(sock_recv + 1, &read_fds, NULL, NULL, &select_timeout);
if (select_return > 0 && FD_ISSET(sock_recv, &read_fds)) {
// ...
}
}
}
The problem is that if there isn’t a process already sending UDP packets to port 18902 before RelayStart() is called, select() will always return 0. So, for example, I can’t restart the sender without restarting the thread (in the correct order.)
Everything seems to work fine as long as the sender is started first.
The
Runthread only constructsread_fdsonce.The
selectcall updatesread_fdsto have all its bits cleared for all descriptors that did not have data ready, and all its bits set for those that were set before and do have data ready.Hence, if no descriptor has any data ready and the
selectcall times out (and returns 0), all the bits inread_fdsare now cleared. Further calls passing the same all-zero bit-mask will scan no file descriptors.You can either re-construct the read-set on each trip inside the loop:
or use an auxiliary variable with a copy of the bit-set:
(Or, of course, there are non-
selectinterfaces that are easier to use in some ways.)