[英]epoll_wait() in a thread after close()
我有一个主线程和一个工作线程。 工作线程的代码如下所示:
thread = ::std::thread([this]() {
struct epoll_event events[50];
for (;;)
{
if (int const n =
epoll_wait(efd, events, 50, -1))
{
//...
我希望主线程中的close(efd)
会导致工作线程的epoll_wait()
调用返回,但它没有发生。 我该怎么做才能退出工作线程的无限循环?
最简单的解决方案大概如下:
让工作线程在 epoll 集中包含管道的读取端。
如果epoll_wait
指示管道可读,则对工作线程进行编码以终止。
要终止工作线程,请向管道的写端写入一个字节。
让worker线程关闭epoll socket,或者加入worker后关闭。
最好的办法是使用从主线程到 epoll 工作线程的显式信号(我的意思是,普通意义上的信号;不一定是 POSIX 信号)。
为此目的使用管道的技术已经过尝试并且是正确的,但还有更好的选择:查看eventfd 。 要使用它,您需要创建一个 eventfd 文件描述符并将其添加到 epoll 集中。 通过写入 8 字节值(值 1 可以)从主线程发出信号。
当工作线程在 eventfd 上看到一个事件时,它知道它已被发出信号并应采取相应的行动。
与使用管道相比的主要优点是它只需要一个文件描述符,并且您不必担心写入管道时可能会阻塞。
我刚刚遇到了同样的问题,在做了一些测试后,这对我有用:
我有一个线程在 epoll_wait 服务和等待,还有一个线程关闭连接。 结束语是这样的:
shutdown(server_fd, SHUT_RDWR);
close(server_fd);
并且服务器线程无限期挂起(除非服务器线程是主线程)。 所以我隔离了这个问题进行了一些实验并尝试更好地理解它,并发现删除关闭行并且只关闭server_fd而不关闭它正在完成工作。
所以,我在很长一段时间后回答我自己的问题。 正如我在评论中指出的那样,也可以向包含epoll_wait()
的线程发送信号。
bool terminate_meh{};
extern "C"
{
static void sig_handler(int) noexcept
{
terminate_meh = true;
}
}
{
struct sigaction act{};
act.sa_handler = sig_handler;
sigemptyset(&act.sa_mask);
sigaction(SIGUSR2, &act, {});
}
当你想杀死等待线程时:
pthread_kill(thread.native_handle(), SIGUSR2);
任何阻塞函数( epoll_wait()
)都将被中断,并且terminate_meh
将被设置。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.