【发布时间】:2010-09-02 06:43:02
【问题描述】:
在 Linux 中,如果我们从一个线程调用阻塞 recv 并从另一个线程关闭同一个套接字,recv 不会退出。
为什么?
【问题讨论】:
在 Linux 中,如果我们从一个线程调用阻塞 recv 并从另一个线程关闭同一个套接字,recv 不会退出。
为什么?
【问题讨论】:
“为什么”只是它的设计原理。
在内核中,recv() 调用在文件描述符对应的struct file 上调用了fget(),这将阻止它被释放,直到对应的fput()。
您只需要更改您的设计(无论如何,您的设计本质上是活泼的 - 要发生这种情况,您必须没有锁定保护用户空间中的文件描述符,这意味着 close() 可能只是发生了 在recv() 调用之前 - 文件描述符甚至被重用于其他东西)。
如果你想唤醒另一个在文件描述符上阻塞的线程,你应该让它阻塞在select(),而不是在文件描述符集中包含一个可以被主线程写入的管道。
【讨论】:
close(),你应该不在文件描述符上调用recv()。如果你很幸运,你只会得到EBADF,但如果你不走运,你可以从另一个线程新打开的完全不同的套接字中读取。
检查套接字的所有文件描述符是否已关闭。如果在“远程端”有任何保持打开状态(假设这是您尝试关闭的那个),则为“peer has not performed an orderly shutdown”。
如果这仍然不起作用,请在远程端调用shutdown(sock, SHUT_RDWR),这将关闭套接字,无论引用计数如何。
【讨论】: