【问题标题】:Blocking recv doesn't exit when closing socket from another thread?从另一个线程关闭套接字时阻塞recv不会退出?
【发布时间】:2010-09-02 06:43:02
【问题描述】:

在 Linux 中,如果我们从一个线程调用阻塞 recv 并从另一个线程关闭同一个套接字,recv 不会退出。

为什么?

【问题讨论】:

    标签: c linux sockets


    【解决方案1】:

    “为什么”只是它的设计原理。

    在内核中,recv() 调用在文件描述符对应的struct file 上调用了fget(),这将阻止它被释放,直到对应的fput()。

    您只需要更改您的设计(无论如何,您的设计本质上是活泼的 - 要发生这种情况,您必须没有锁定保护用户空间中的文件描述符,这意味着 close() 可能只是发生了 在recv() 调用之前 - 文件描述符甚至被重用于其他东西)。


    如果你想唤醒另一个在文件描述符上阻塞的线程,你应该让它阻塞在select(),而不是在文件描述符集中包含一个可以被主线程写入的管道。

    【讨论】:

    • 如果我在调用 recv 之前调用 close,它应该可以工作,但是一旦调用在 recv 中,并且如果我从另一个线程调用 close,它就不会被释放。这是正确的吗?
    • @Jay:一旦你调用了close(),你应该不在文件描述符上调用recv()。如果你很幸运,你只会得到EBADF,但如果你不走运,你可以从另一个线程新打开的完全不同的套接字中读取。
    • 我认为你没有抓住重点。 Pater 正在尝试在已经位于 recv() 内部的套接字上调用 close() 以强制 recv() 立即退出。这适用于其他系统,但不适用于 Linux。
    • @Remy:我知道这一点,正如我在回答中所说的那样——这种行为是设计使然。我的第一条评论与 OP 评论有关。
    【解决方案2】:

    检查套接字的所有文件描述符是否已关闭。如果在“远程端”有任何保持打开状态(假设这是您尝试关闭的那个),则为“peer has not performed an orderly shutdown”。

    如果这仍然不起作用,请在远程端调用shutdown(sock, SHUT_RDWR),这将关闭套接字,无论引用计数如何。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2010-10-14
      • 2012-06-11
      • 1970-01-01
      • 2023-03-03
      • 2015-07-30
      • 2022-01-16
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多