繁体   English   中英

close() 之后线程中的 epoll_wait()

[英]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()调用返回,但它没有发生。 我该怎么做才能退出工作线程的无限循环?

最简单的解决方案大概如下:

  1. 让工作线程在 epoll 集中包含管道的读取端。

  2. 如果epoll_wait指示管道可读,则对工作线程进行编码以终止。

  3. 要终止工作线程,请向管道的写端写入一个字节。

  4. 让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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM