【问题标题】:epoll_wait() in a thread after close()关闭()之后的线程中的epoll_wait()
【发布时间】:2015-09-21 09:40:11
【问题描述】:

我有一个主线程和一个工作线程。工作线程的代码如下所示:

thread = ::std::thread([this]() {
    struct epoll_event events[50];

    for (;;)
    {
      if (int const n =
        epoll_wait(efd, events, 50, -1))
      {
      //...

我希望主线程中的close(efd) 会导致工作线程的epoll_wait() 调用返回,但它没有发生。如何退出工作线程的无限循环?

【问题讨论】:

  • 您决不能在一个线程中释放资源,而另一个线程正在或可能正在使用它。你的外在问题是什么?你到底想做什么?
  • @DavidSchwartz +1 表示“外部问题”:-|
  • 我想我可以使用 efd 作为标志来指示线程退出。如果超时为-1,我如何完全退出对epoll_wait() 的调用?给自己发信号?

标签: c++ linux multithreading


【解决方案1】:

最好的办法是使用从主线程到 epoll 工作线程的显式信号(我的意思是普通意义上的信号;不一定是 POSIX 信号)。

为此目的使用管道的技术已经过验证,但还有更好的选择:查看eventfd。要使用它,您将创建一个 eventfd 文件描述符并将其添加到 epoll 集中。通过写入一个 8 字节的值从主线程发出信号(值 1 很好)。

当工作线程在 eventfd 上看到一个事件时,它就知道它已收到信号并应采取相应的行动。

使用管道的主要优点是它只需要一个文件描述符,并且您不必担心写入管道时可能会阻塞。

【讨论】:

    【解决方案2】:

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

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

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

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

    4. 让worker线程关闭epoll socket,或者加入worker后关闭。

    【讨论】:

      【解决方案3】:

      我刚刚遇到了同样的问题,在做了一些测试后,这对我有用:

      我有一个线程在 epoll_wait 服务和等待,一个线程关闭连接。 结束线程是这样的:

      shutdown(server_fd, SHUT_RDWR);
      close(server_fd);
      

      并且服务器线程无限期挂起(除非服务器线程是主线程)。所以我将问题隔离出来进行了一些实验并尝试更好地理解它,并发现删除关闭线并仅关闭server_fd而不关闭它正在完成工作。

      【讨论】:

      • 这是一个很好的技巧,但仅适用于服务器套接字,不适用于 epoll 文件描述符。
      【解决方案4】:

      所以,我在很长一段时间后回答了我自己的问题。正如我在 cmets 中所指出的,也可以向包含 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 将被设置。

      【讨论】:

        猜你喜欢
        • 2011-06-21
        • 2013-09-07
        • 1970-01-01
        • 2019-10-27
        • 1970-01-01
        • 1970-01-01
        • 2014-03-10
        • 2021-08-16
        • 1970-01-01
        相关资源
        最近更新 更多