Skip to content

Commit c773649

Browse files
committed
init: improves file descriptors accounting and docs
The current logic for file descriptor accounting is pretty convoluted and hard to follow. This is partially caused by the lack of documentation plus non-intuitive variable naming (which was more intuitive when fewer things were accounted for, but hasn't aged well). This has led to this accounting being error-prone and hard to maintain (as shown in he previous commit). Redefine some of the constants, plus document what are we accounting for so this can be extended more easily Remove FreeBSD workaround to #2695
1 parent 29008a7 commit c773649

File tree

1 file changed

+23
-17
lines changed

1 file changed

+23
-17
lines changed

src/init.cpp

Lines changed: 23 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -147,11 +147,12 @@ static constexpr bool DEFAULT_STOPAFTERBLOCKIMPORT{false};
147147
// Win32 LevelDB doesn't use filedescriptors, and the ones used for
148148
// accessing block files don't count towards the fd_set size limit
149149
// anyway.
150-
#define MIN_CORE_FILEDESCRIPTORS 0
150+
#define MIN_LEVELDB_FDS 0
151151
#else
152-
#define MIN_CORE_FILEDESCRIPTORS 150
152+
#define MIN_LEVELDB_FDS 150
153153
#endif
154154

155+
static constexpr int MIN_CORE_FDS = MIN_LEVELDB_FDS + NUM_FDS_MESSAGE_CAPTURE;
155156
static const char* DEFAULT_ASMAP_FILENAME="ip_asn.map";
156157

157158
/**
@@ -834,8 +835,7 @@ void InitLogging(const ArgsManager& args)
834835
namespace { // Variables internal to initialization process only
835836

836837
int nMaxConnections;
837-
int nUserMaxConnections;
838-
int nFD;
838+
int available_fds;
839839
ServiceFlags nLocalServices = ServiceFlags(NODE_NETWORK_LIMITED | NODE_WITNESS);
840840
int64_t peer_connect_timeout;
841841
std::set<BlockFilterType> g_enabled_filter_types;
@@ -987,25 +987,31 @@ bool AppInitParameterInteraction(const ArgsManager& args)
987987
return InitError(Untranslated("Cannot set -listen=0 together with -listenonion=1"));
988988
}
989989

990-
// Make sure enough file descriptors are available
991-
int nBind = std::max(nUserBind, size_t(1));
992-
nUserMaxConnections = args.GetIntArg("-maxconnections", DEFAULT_MAX_PEER_CONNECTIONS);
993-
nMaxConnections = std::max(nUserMaxConnections, 0);
990+
// Make sure enough file descriptors are available. We need to reserve enough FDs to account for the bare minimum,
991+
// plus all manual connections and all bound interfaces. Any remainder will be available for connection sockets
994992

995-
nFD = RaiseFileDescriptorLimit(nMaxConnections + MIN_CORE_FILEDESCRIPTORS + MAX_ADDNODE_CONNECTIONS + nBind + NUM_FDS_MESSAGE_CAPTURE);
993+
// Number of bound interfaces (we have at least one)
994+
int nBind = std::max(nUserBind, size_t(1));
995+
// Maximum number of connections with other nodes, this accounts for all types of outbounds and inbounds except for manual
996+
int user_max_connection = args.GetIntArg("-maxconnections", DEFAULT_MAX_PEER_CONNECTIONS);
997+
nMaxConnections = std::max(user_max_connection, 0);
998+
// Reserve enough FDs to account for the bare minimum, plus any manual connections, plus the bound interfaces
999+
int min_required_fds = MIN_CORE_FDS + MAX_ADDNODE_CONNECTIONS + nBind;
1000+
1001+
// Try raising the FD limit to what we need (available_fds may be smaller than the requested amount if this fails)
1002+
available_fds = RaiseFileDescriptorLimit(nMaxConnections + min_required_fds);
9961003
// If we are using select instead of poll, our actual limit may be even smaller
9971004
#ifndef USE_POLL
998-
nFD = std::min(FD_SETSIZE, nFD);
1005+
available_fds = std::min(FD_SETSIZE, available_fds);
9991006
#endif
1000-
if (nFD < MIN_CORE_FILEDESCRIPTORS)
1001-
return InitError(_("Not enough file descriptors available."));
1007+
if (available_fds < min_required_fds)
1008+
return InitError(strprintf(_("Not enough file descriptors available. %d available, %d required."), available_fds, min_required_fds));
10021009

10031010
// Trim requested connection counts, to fit into system limitations
1004-
// <int> in std::min<int>(...) to work around FreeBSD compilation issue described in #2695
1005-
nMaxConnections = std::max(std::min<int>(nMaxConnections, nFD - nBind - MIN_CORE_FILEDESCRIPTORS - MAX_ADDNODE_CONNECTIONS - NUM_FDS_MESSAGE_CAPTURE), 0);
1011+
nMaxConnections = std::min(available_fds - min_required_fds, nMaxConnections);
10061012

1007-
if (nMaxConnections < nUserMaxConnections)
1008-
InitWarning(strprintf(_("Reducing -maxconnections from %d to %d, because of system limitations."), nUserMaxConnections, nMaxConnections));
1013+
if (nMaxConnections < user_max_connection)
1014+
InitWarning(strprintf(_("Reducing -maxconnections from %d to %d, because of system limitations."), user_max_connection, nMaxConnections));
10091015

10101016
// ********************************************************* Step 3: parameter-to-internal-flags
10111017
if (auto result{init::SetLoggingCategories(args)}; !result) return InitError(util::ErrorString(result));
@@ -1153,7 +1159,7 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info)
11531159
return false;
11541160
}
11551161

1156-
LogPrintf("Using at most %i automatic connections (%i file descriptors available)\n", nMaxConnections, nFD);
1162+
LogPrintf("Using at most %i automatic connections (%i file descriptors available)\n", nMaxConnections, available_fds);
11571163

11581164
// Warn about relative -datadir path.
11591165
if (args.IsArgSet("-datadir") && !args.GetPathArg("-datadir").is_absolute()) {

0 commit comments

Comments
 (0)