accept (EMFILE错误)文件描述符用尽解决方案

问题描述:

accept处理连接时,若出现 EMFILE 错误不进行处理,则内核间隔性尝试连接,导致整个网络设计程序崩溃,因此需要处理这不当的请求。对于用户而言,处理该请求的关键就是文件描述符,然而没有请求成功就不存在相应的文件描述符,这是一个麻烦的问题,下面借由muduo库(方法来源于libev)简单说明一下解决方案。

方案:

事先创建一个指向空文件( /dev/null )的 idlefd 文件描述符,当出现 EMFILE错误时,将该文件描述符关闭,并重新接收请求;此时idlefd就是连接请求的 fd ,该fd是不当请求,将其关闭::close(fd),然后重置idlefd文件描述符指向,以备后续使用。

程序

(摘自陈硕的高并发muduo网络库,Acceptor封装类)

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);
    }
  }
}

你可能感兴趣的:(C++,网络库)