Skip to content

Commit 2756797

Browse files
committed
Merge bitcoin/bitcoin#30065: init: fixes file descriptor accounting
d4c7c40 init: error out if -maxconnections is negative (Sergi Delgado Segura) c773649 init: improves file descriptors accounting and docs (Sergi Delgado Segura) 29008a7 init: fixes fd accounting regarding poll/select (Sergi Delgado Segura) Pull request description: 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 the first commit of this PR). Redefine some of the constants, plus document what are we accounting for so this can be extended more easily Fixes #18911 ACKs for top commit: sr-gi: > ACK [d4c7c40](bitcoin/bitcoin@d4c7c40) naumenkogs: ACK d4c7c40 vasild: ACK d4c7c40 TheCharlatan: ACK d4c7c40 Tree-SHA512: 1524d10c8ad8f354f6ab9c244699adbcdae2dd7aba37de5b8f9e177c629e8a2cce0f6e8117e076dde3a592f5283bd30a4201db96a3c011e335c02d1fde7414bc
2 parents e4fb97a + d4c7c40 commit 2756797

File tree

1 file changed

+28
-22
lines changed

1 file changed

+28
-22
lines changed

src/init.cpp

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

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

158159
/**
@@ -838,8 +839,7 @@ void InitLogging(const ArgsManager& args)
838839
namespace { // Variables internal to initialization process only
839840

840841
int nMaxConnections;
841-
int nUserMaxConnections;
842-
int nFD;
842+
int available_fds;
843843
ServiceFlags nLocalServices = ServiceFlags(NODE_NETWORK_LIMITED | NODE_WITNESS);
844844
int64_t peer_connect_timeout;
845845
std::set<BlockFilterType> g_enabled_filter_types;
@@ -991,27 +991,33 @@ bool AppInitParameterInteraction(const ArgsManager& args)
991991
return InitError(Untranslated("Cannot set -listen=0 together with -listenonion=1"));
992992
}
993993

994-
// Make sure enough file descriptors are available
995-
int nBind = std::max(nUserBind, size_t(1));
996-
nUserMaxConnections = args.GetIntArg("-maxconnections", DEFAULT_MAX_PEER_CONNECTIONS);
997-
nMaxConnections = std::max(nUserMaxConnections, 0);
998-
999-
nFD = RaiseFileDescriptorLimit(nMaxConnections + MIN_CORE_FILEDESCRIPTORS + MAX_ADDNODE_CONNECTIONS + nBind + NUM_FDS_MESSAGE_CAPTURE);
994+
// Make sure enough file descriptors are available. We need to reserve enough FDs to account for the bare minimum,
995+
// plus all manual connections and all bound interfaces. Any remainder will be available for connection sockets
1000996

1001-
#ifdef USE_POLL
1002-
int fd_max = nFD;
1003-
#else
1004-
int fd_max = FD_SETSIZE;
997+
// Number of bound interfaces (we have at least one)
998+
int nBind = std::max(nUserBind, size_t(1));
999+
// Maximum number of connections with other nodes, this accounts for all types of outbounds and inbounds except for manual
1000+
int user_max_connection = args.GetIntArg("-maxconnections", DEFAULT_MAX_PEER_CONNECTIONS);
1001+
if (user_max_connection < 0) {
1002+
return InitError(Untranslated("-maxconnections must be greater or equal than zero"));
1003+
}
1004+
// Reserve enough FDs to account for the bare minimum, plus any manual connections, plus the bound interfaces
1005+
int min_required_fds = MIN_CORE_FDS + MAX_ADDNODE_CONNECTIONS + nBind;
1006+
1007+
// Try raising the FD limit to what we need (available_fds may be smaller than the requested amount if this fails)
1008+
available_fds = RaiseFileDescriptorLimit(user_max_connection + min_required_fds);
1009+
// If we are using select instead of poll, our actual limit may be even smaller
1010+
#ifndef USE_POLL
1011+
available_fds = std::min(FD_SETSIZE, available_fds);
10051012
#endif
1013+
if (available_fds < min_required_fds)
1014+
return InitError(strprintf(_("Not enough file descriptors available. %d available, %d required."), available_fds, min_required_fds));
1015+
10061016
// Trim requested connection counts, to fit into system limitations
1007-
// <int> in std::min<int>(...) to work around FreeBSD compilation issue described in #2695
1008-
nMaxConnections = std::max(std::min<int>(nMaxConnections, fd_max - nBind - MIN_CORE_FILEDESCRIPTORS - MAX_ADDNODE_CONNECTIONS - NUM_FDS_MESSAGE_CAPTURE), 0);
1009-
if (nFD < MIN_CORE_FILEDESCRIPTORS)
1010-
return InitError(_("Not enough file descriptors available."));
1011-
nMaxConnections = std::min(nFD - MIN_CORE_FILEDESCRIPTORS - MAX_ADDNODE_CONNECTIONS - NUM_FDS_MESSAGE_CAPTURE, nMaxConnections);
1017+
nMaxConnections = std::min(available_fds - min_required_fds, user_max_connection);
10121018

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

10161022
// ********************************************************* Step 3: parameter-to-internal-flags
10171023
if (auto result{init::SetLoggingCategories(args)}; !result) return InitError(util::ErrorString(result));
@@ -1159,7 +1165,7 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info)
11591165
return false;
11601166
}
11611167

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

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

0 commit comments

Comments
 (0)