【发布时间】:2013-06-29 20:32:36
【问题描述】:
根据“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提供了一个方法来实现这一点,他的方法将socket数据(可能是脏数据或者退出消息数据)写入wakeup select。我将在那里进行测试并更新结果。
2) 还有一点要提一下,关闭套接字并不能保证唤醒选择函数调用,请参阅this post。
[更新2]
在做了许多测试之后,这里有一些关于唤醒 select 的事实:
1) 如果 select 监视的套接字被 另一个应用程序 关闭,则 select() 调用
会立即醒来。此后,从套接字读取或写入套接字将返回 0 且 errno = 0
2) 如果select监听的socket被同一个应用的另一个线程关闭了,
如果没有数据要读取或写入,则 select() 直到超时才会唤醒。选择超时后,进行读/写操作会导致错误,errno = EBADF
(因为在超时期间socket已经被另一个线程关闭了)
【问题讨论】:
-
写入关闭的连接不会返回零。只有阅读才能做到这一点。
标签: c++ linux multithreading sockets tcp