根据“man select”信息:
"On success, select() and pselect() return the number of file descrip‐
tors contained in the three returned descriptor sets which may be zero
if the timeout expires before anything interesting happens. On error,
-1 is returned, and errno is set appropriately; the sets and timeout become
undefined, so do not rely on their contents after an error."
Select 会唤醒,因为:
1)read/write availability
2)select error
3)descriptoris closed.
但是,如果没有可用数据并且 select 仍在超时范围内,我们如何从另一个线程中唤醒 select()?
[更新]
伪代码
// Thread blocks on Select
void *SocketReadThread(void *param){
...
while(!(ReadThread*)param->ExitThread()) {
struct timeval timeout;
timeout.tv_sec = 60; //one minute
timeout.tv_usec = 0;
fd_set rds;
FD_ZERO(&rds);
FD_SET(sockfd, &rds)'
//actually, the first parameter of select() is
//ignored on windows, though on linux this parameter
//should be (maximum socket value + 1)
int ret = select(sockfd + 1, &rds, NULL, NULL, &timeout );
//handle the result
//might break from here
}
return NULL;
}
//main Thread
int main(){
//create the SocketReadThread
ReaderThread* rthread = new ReaderThread;
pthread_create(&pthreadid, NULL, SocketReaderThread,
NULL, (void*)rthread);
// do lots of things here
............................
//now main thread wants to exit SocketReaderThread
//it sets the internal state of ReadThread as true
rthread->SetExitFlag(true);
//but how to wake up select ??????????????????
//if SocketReaderThread currently blocks on select
}
[更新]
1)@trojanfoe 提供了一种方法来实现这一点,他的方法将套接字数据(可能是脏数据或退出消息数据)写入唤醒选择。我将在那里进行测试并更新结果。
2)还有一点要提一下,关闭套接字并不能保证唤醒选择函数调用,请参阅这篇文章。
[UPDATE2]
经过多次测试,以下是关于唤醒 select 的一些事实:
1)如果 select 监视的套接字被另一个应用程序关闭,则 select() 调用将立即唤醒。此后,读取或写入套接字将返回 0 且 errno = 0
2) 如果 select 监视的套接字被同一应用程序的另一个线程关闭,则 select() 将在超时之前唤醒没有要读取或写入的数据。选择超时后,进行读/写操作会导致错误 errno = EBADF(因为在超时期间套接字已被另一个线程关闭)