Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Do not count free FDs in userland. #1928

Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 0 additions & 5 deletions utilities/xmlrpcpp/include/xmlrpcpp/XmlRpcServer.h
Original file line number Diff line number Diff line change
Expand Up @@ -96,9 +96,6 @@ namespace XmlRpc {
//! Create a new connection object for processing requests from a specific client.
virtual XmlRpcServerConnection* createConnection(int socket);

//! Count number of free file descriptors
int countFreeFDs();

// Whether the introspection API is supported by this server
bool _introspectionEnabled;

Expand All @@ -123,8 +120,6 @@ namespace XmlRpc {
// Retry time for accept.
double _accept_retry_time_sec;

// Minimum number of free file descriptors before rejecting clients.
static const int FREE_FD_BUFFER;
#ifndef _WINDOWS
// List of all file descriptors, used for counting open files.
std::vector<struct pollfd> pollfds;
Expand Down
61 changes: 3 additions & 58 deletions utilities/xmlrpcpp/src/XmlRpcServer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@

using namespace XmlRpc;

const int XmlRpcServer::FREE_FD_BUFFER = 32;
const double XmlRpcServer::ACCEPT_RETRY_INTERVAL_SEC = 1.0;

XmlRpcServer::XmlRpcServer()
Expand Down Expand Up @@ -191,17 +190,15 @@ XmlRpcServer::acceptConnection()
{
//this->close();
XmlRpcUtil::error("XmlRpcServer::acceptConnection: Could not accept connection (%s).", XmlRpcSocket::getErrorMsg().c_str());
if (XmlRpcSocket::getError() == EMFILE) {
XmlRpcUtil::error("XmlRpcServer::acceptConnection: there is not enough free file descriptors.");
}

// Note that there was an accept error; retry in 1 second
_accept_error = true;
_accept_retry_time_sec = _disp.getTime() + ACCEPT_RETRY_INTERVAL_SEC;
return 0; // Stop monitoring this FD
}
else if( countFreeFDs() < FREE_FD_BUFFER )
{
XmlRpcSocket::close(s);
XmlRpcUtil::error("XmlRpcServer::acceptConnection: Rejecting client, not enough free file descriptors");
}
else if ( ! XmlRpcSocket::setNonBlocking(s))
{
XmlRpcSocket::close(s);
Expand All @@ -216,58 +213,6 @@ XmlRpcServer::acceptConnection()
return XmlRpcDispatch::ReadableEvent; // Continue to monitor this fd
}

int XmlRpcServer::countFreeFDs() {
// NOTE(austin): this function is not free, but in a few small tests it only
// takes about 1.2mS when querying 50k file descriptors.
//
// If the underlying system calls here fail, this will print an error and
// return 0

#if !defined(_WINDOWS)
int free_fds = 0;

struct rlimit limit = { .rlim_cur = 0, .rlim_max = 0 };

// Get the current soft limit on the number of file descriptors.
if(getrlimit(RLIMIT_NOFILE, &limit) == 0) {
// If we have infinite file descriptors, always return FREE_FD_BUFFER so
// that we never hit the low-water mark.
if( limit.rlim_max == RLIM_INFINITY ) {
return FREE_FD_BUFFER;
}

// Poll the available file descriptors.
// The POSIX specification guarantees that rlim_cur will always be less or
// equal to the process's initial rlim_max, so we don't need an additonal
// bounds check here.
if(poll(&pollfds[0], limit.rlim_cur, 1) >= 0) {
for(rlim_t i=0; i<limit.rlim_cur; i++) {
if(pollfds[i].revents & POLLNVAL) {
free_fds++;
}
}
} else {
// poll() may fail if interrupted, if the pollfds array is a bad pointer,
// if nfds exceeds RLIMIT_NOFILE, or if the system is out of memory.
XmlRpcUtil::error("XmlRpcServer::countFreeFDs: poll() failed: %s",
strerror(errno));
}
} else {
// The man page for getrlimit says that it can fail if the requested
// resource is invalid or the second argument is invalid. I'm not sure
// either of these can actually fail in this code, but it's better to
// check.
XmlRpcUtil::error("XmlRpcServer::countFreeFDs: Could not get open file "
"limit, getrlimit() failed: %s", strerror(errno));
}

return free_fds;
#else
return FREE_FD_BUFFER;
#endif
}


// Create a new connection object for processing requests from a specific client.
XmlRpcServerConnection*
XmlRpcServer::createConnection(int s)
Expand Down