赞
踩
若accpet(2) 返回 EMFILE 该如何应对?这意味着本进程的文件描述符已经到达上限,无法为新连接创建 socket 文件描述符。但是,既然没有 socket 文件描述符来表示这个连接,我们就无法 close(2)它。程序继续运行,回到epoll_wait处 。这时 epoll_wait 会马上返回,因为新连接还在等待处理,listening fd 还是可读的。这样程序就陷入了 busy loop,CPU 占用率接近 100%,这既影响同一 eventloop 上的连接,也影响同一机器上的其他服务。
陈硕的 《linux多线程服务端编程》中提到了以下几种做法:
muduo网络库中使用的是,第6种,代码如下:
void Acceptor::handleRead() { loop_->assertInLoopThread(); InetAddress peerAddr; //FIXME loop until no more int connfd = acceptSocket_.accept(&peerAddr); if (connfd >= 0) { // string hostport = peerAddr.toIpPort(); // LOG_TRACE << "Accepts of " << hostport; if (newConnectionCallback_) { newConnectionCallback_(connfd, peerAddr); } else { sockets::close(connfd); } } else { LOG_SYSERR << "in Acceptor::handleRead"; // Read the section named "The special problem of // accept()ing when you can't" in libev's doc. // By Marc Lehmann, author of libev. if (errno == EMFILE) { // 描述符用尽 ::close(idleFd_); idleFd_ = ::accept(acceptSocket_.fd(), NULL, NULL); ::close(idleFd_); // 再次打开占位 idleFd_ = ::open("/dev/null", O_RDONLY | O_CLOEXEC); } } }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。