[英]close on socket not releasing file descriptor
在对我编写的某些服务器代码进行压力测试时,我注意到即使我在描述符句柄上调用close()(并验证错误的结果),也没有释放描述符,最终导致accept()返回错误“打开文件太多”。
现在我明白这是因为ulimit,我不明白为什么如果我在每个同步接受/读/发送周期后调用close(),我会遇到它?
我通过运行带有lsof的监视来验证描述符实际上是在那里:
ctsvr 9733 mike 1017u sock 0,7 0t0 3323579 can't identify protocol ctsvr 9733 mike 1018u sock 0,7 0t0 3323581 can't identify protocol ...
当然,大约有1000个左右。 此外,使用netstat检查我可以看到没有挂起的TCP状态(没有WAIT或STOPPED或任何东西)。
如果我只是从客户端执行单个connect / send / recv,我会注意到套接字确实保留在lsof中; 所以这甚至不是负载问题。
服务器在Ubuntu Linux 64位计算机上运行。
有什么想法吗?
因此,使用strace(感谢Gearoid),我不知道我是如何生活的,我注意到我实际上是在关闭描述符。
然而。 为了后代,我露出了愚蠢的错误:
Socket::Socket() : impl(new Impl) {
impl->fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
....
}
Socket::ptr_t Socket::accept() {
auto r = ::accept(impl->fd, NULL, NULL);
...
ptr_t s(new Socket);
s->impl->fd = r;
return s;
}
正如您所看到的,我的构造函数立即分配了一个套接字,然后我用accept返回的描述符替换了描述符 - 创建了一个泄漏。 我已经将独立的Acceptor类中的接受代码重构为Socket类而不更改它。
使用strace我可以很容易地看到每次运行socket()导致我的灯泡时刻。
谢谢大家的帮助!
你有没有在close()之后调用perror()? 我认为返回的字符串会给你一些帮助;
您最有可能挂在recv()
或send()
命令上。 考虑使用setsockopt
设置超时。
当套接字在另一端关闭时,我注意到lsof上有类似的输出,但是我的线程在等待数据的recv()
命令上保持套接字打开。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.