Try to increase file descriptor rlimit if necessary

As the default can be too low, especially on OSX.
This commit is contained in:
Pieter Wuille 2013-04-26 00:46:47 +02:00
parent 33029bcedd
commit ba29a5590b
5 changed files with 48 additions and 2 deletions

View file

@ -28,6 +28,15 @@ using namespace boost;
CWallet* pwalletMain; CWallet* pwalletMain;
CClientUIInterface uiInterface; CClientUIInterface uiInterface;
#ifdef WIN32
// Win32 LevelDB doesn't use filedescriptors, and the ones used for
// accessing block files, don't count towards to fd_set size limit
// anyway.
#define MIN_CORE_FILEDESCRIPTORS 0
#else
#define MIN_CORE_FILEDESCRIPTORS 150
#endif
// Used to pass flags to the Bind() function // Used to pass flags to the Bind() function
enum BindFlags { enum BindFlags {
BF_NONE = 0, BF_NONE = 0,
@ -518,6 +527,16 @@ bool AppInit2(boost::thread_group& threadGroup)
SoftSetBoolArg("-rescan", true); SoftSetBoolArg("-rescan", true);
} }
// Make sure enough file descriptors are available
int nBind = std::max((int)mapArgs.count("-bind"), 1);
nMaxConnections = GetArg("-maxconnections", 125);
nMaxConnections = std::max(std::min(nMaxConnections, FD_SETSIZE - nBind - MIN_CORE_FILEDESCRIPTORS), 0);
int nFD = RaiseFileDescriptorLimit(nMaxConnections + MIN_CORE_FILEDESCRIPTORS);
if (nFD < MIN_CORE_FILEDESCRIPTORS)
return InitError(_("Not enough file descriptors available."));
if (nFD - MIN_CORE_FILEDESCRIPTORS < nMaxConnections)
nMaxConnections = nFD - MIN_CORE_FILEDESCRIPTORS;
// ********************************************************* Step 3: parameter-to-internal-flags // ********************************************************* Step 3: parameter-to-internal-flags
fDebug = GetBoolArg("-debug"); fDebug = GetBoolArg("-debug");
@ -594,6 +613,7 @@ bool AppInit2(boost::thread_group& threadGroup)
printf("Startup time: %s\n", DateTimeStrFormat("%Y-%m-%d %H:%M:%S", GetTime()).c_str()); printf("Startup time: %s\n", DateTimeStrFormat("%Y-%m-%d %H:%M:%S", GetTime()).c_str());
printf("Default data directory %s\n", GetDefaultDataDir().string().c_str()); printf("Default data directory %s\n", GetDefaultDataDir().string().c_str());
printf("Used data directory %s\n", strDataDir.c_str()); printf("Used data directory %s\n", strDataDir.c_str());
printf("Using at most %i connections (%i file descriptors available)\n", nMaxConnections, nFD);
std::ostringstream strErrors; std::ostringstream strErrors;
if (fDaemon) if (fDaemon)

View file

@ -48,6 +48,7 @@ static CNode* pnodeSync = NULL;
uint64 nLocalHostNonce = 0; uint64 nLocalHostNonce = 0;
static std::vector<SOCKET> vhListenSocket; static std::vector<SOCKET> vhListenSocket;
CAddrMan addrman; CAddrMan addrman;
int nMaxConnections = 125;
vector<CNode*> vNodes; vector<CNode*> vNodes;
CCriticalSection cs_vNodes; CCriticalSection cs_vNodes;
@ -908,7 +909,7 @@ void ThreadSocketHandler()
if (nErr != WSAEWOULDBLOCK) if (nErr != WSAEWOULDBLOCK)
printf("socket error accept failed: %d\n", nErr); printf("socket error accept failed: %d\n", nErr);
} }
else if (nInbound >= GetArg("-maxconnections", 125) - MAX_OUTBOUND_CONNECTIONS) else if (nInbound >= nMaxConnections - MAX_OUTBOUND_CONNECTIONS)
{ {
{ {
LOCK(cs_setservAddNodeAddresses); LOCK(cs_setservAddNodeAddresses);
@ -1803,7 +1804,7 @@ void StartNode(boost::thread_group& threadGroup)
{ {
if (semOutbound == NULL) { if (semOutbound == NULL) {
// initialize semaphore // initialize semaphore
int nMaxOutbound = min(MAX_OUTBOUND_CONNECTIONS, (int)GetArg("-maxconnections", 125)); int nMaxOutbound = min(MAX_OUTBOUND_CONNECTIONS, nMaxConnections);
semOutbound = new CSemaphore(nMaxOutbound); semOutbound = new CSemaphore(nMaxOutbound);
} }

View file

@ -74,6 +74,7 @@ extern bool fDiscover;
extern uint64 nLocalServices; extern uint64 nLocalServices;
extern uint64 nLocalHostNonce; extern uint64 nLocalHostNonce;
extern CAddrMan addrman; extern CAddrMan addrman;
extern int nMaxConnections;
extern std::vector<CNode*> vNodes; extern std::vector<CNode*> vNodes;
extern CCriticalSection cs_vNodes; extern CCriticalSection cs_vNodes;

View file

@ -10,6 +10,7 @@
#endif #endif
#include <fcntl.h> #include <fcntl.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <sys/resource.h>
#endif #endif
#include "util.h" #include "util.h"
@ -1167,6 +1168,28 @@ bool TruncateFile(FILE *file, unsigned int length) {
#endif #endif
} }
// this function tries to raise the file descriptor limit to the requested number.
// It returns the actual file descriptor limit (which may be more or less than nMinFD)
int RaiseFileDescriptorLimit(int nMinFD) {
#if defined(WIN32)
return 2048;
#else
struct rlimit limitFD;
if (getrlimit(RLIMIT_NOFILE, &limitFD) != -1) {
if (limitFD.rlim_cur < (rlim_t)nMinFD) {
limitFD.rlim_cur = nMinFD;
if (limitFD.rlim_cur > limitFD.rlim_max)
limitFD.rlim_cur = limitFD.rlim_max;
setrlimit(RLIMIT_NOFILE, &limitFD);
getrlimit(RLIMIT_NOFILE, &limitFD);
}
return limitFD.rlim_cur;
}
return nMinFD; // getrlimit failed, assume it's fine
#endif
}
// this function tries to make a particular range of a file allocated (corresponding to disk space) // this function tries to make a particular range of a file allocated (corresponding to disk space)
// it is advisory, and the range specified in the arguments will never contain live data // it is advisory, and the range specified in the arguments will never contain live data
void AllocateFileRange(FILE *file, unsigned int offset, unsigned int length) { void AllocateFileRange(FILE *file, unsigned int offset, unsigned int length) {

View file

@ -197,6 +197,7 @@ bool WildcardMatch(const std::string& str, const std::string& mask);
void FileCommit(FILE *fileout); void FileCommit(FILE *fileout);
int GetFilesize(FILE* file); int GetFilesize(FILE* file);
bool TruncateFile(FILE *file, unsigned int length); bool TruncateFile(FILE *file, unsigned int length);
int RaiseFileDescriptorLimit(int nMinFD);
void AllocateFileRange(FILE *file, unsigned int offset, unsigned int length); void AllocateFileRange(FILE *file, unsigned int offset, unsigned int length);
bool RenameOver(boost::filesystem::path src, boost::filesystem::path dest); bool RenameOver(boost::filesystem::path src, boost::filesystem::path dest);
boost::filesystem::path GetDefaultDataDir(); boost::filesystem::path GetDefaultDataDir();