在Linux中,如果我们从一个线程调用阻塞recv
并从另一个线程关闭同一个套接字,则recv
不会退出。
为什么?
答案 0 :(得分:11)
“为什么”只是因为设计的原因。
在内核中,recv()
调用在与文件描述符对应的fget()
上调用struct file
,这将阻止它被释放,直到相应的fput()
你只需要改变你的设计(无论如何你的设计都是天生的 - 为了实现这一点,你必须没有锁定来保护用户空间中的文件描述符,这意味着close()
可能只发生了< em>在 recv()
调用之前 - 文件描述符甚至被重用于其他东西)。
如果你想唤醒另一个阻塞文件描述符的线程,你应该让它在select()
上阻塞,而是在主线程可以写入的文件描述符集中包含一个管道。
答案 1 :(得分:7)
检查套接字的所有文件描述符是否已关闭。如果在“远程端”仍然打开(假设这是您尝试关闭的那个),则为“peer has not performed an orderly shutdown”。
如果仍然无效,请拨打远端的shutdown(sock, SHUT_RDWR)
,无论引用次数如何,都会关闭套接字。