小智 13
调用shutdown(sock, SHUT_RDWR)
套接字,然后等待线程退出.(即pthread_join
).
你会认为这close()
会解锁recvfrom()
,但它不会在Linux上.
下面是一个使用 select() 来处理这个问题的简单方法的草图:
// Note: untested code, may contain typos or bugs
static volatile bool _threadGoAway = false;
void MyThread(void *)
{
int fd = (your socket fd);
while(1)
{
struct timeval timeout = {1, 0}; // make select() return once per second
fd_set readSet;
FD_ZERO(&readSet);
FD_SET(fd, &readSet);
if (select(fd+1, &readSet, NULL, NULL, &timeout) >= 0)
{
if (_threadGoAway)
{
printf("MyThread: main thread wants me to scram, bye bye!\n");
return;
}
else if (FD_ISSET(fd, &readSet))
{
char buf[1024];
int numBytes = recvfrom(fd, buf, sizeof(buf), 0);
[...handle the received bytes here...]
}
}
else perror("select");
}
}
// To be called by the main thread at shutdown time
void MakeTheReadThreadGoAway()
{
_threadGoAway = true;
(void) pthread_join(_thread, NULL); // may block for up to one second
}
Run Code Online (Sandbox Code Playgroud)
一个更优雅的方法是避免使用 select 的超时功能,而是创建一个套接字对(使用 socketpair())并让主线程在需要 I/O 线程时在它的套接字对的末尾发送一个字节离开,并在 I/O 线程在套接字对另一端的套接字上接收到一个字节时退出。不过,我会将其作为练习留给读者。:)
将套接字设置为非阻塞模式通常也是一个好主意,以避免即使在 select() 指示套接字已准备好读取之后 recvfrom() 调用也可能阻塞的(小但非零)机会,如所描述这里。但是阻塞模式对于您的目的来说可能“足够好”。
不是答案,但 Linux close 手册页包含有趣的引用:
当同一进程中的其他线程中的系统调用可能正在使用文件描述符时,关闭它们可能是不明智的。由于文件描述符可以重复使用,因此存在一些模糊的竞争条件,可能会导致意想不到的副作用。