@@ -147,11 +147,12 @@ static constexpr bool DEFAULT_STOPAFTERBLOCKIMPORT{false};
147
147
// Win32 LevelDB doesn't use filedescriptors, and the ones used for
148
148
// accessing block files don't count towards the fd_set size limit
149
149
// anyway.
150
- #define MIN_CORE_FILEDESCRIPTORS 0
150
+ #define MIN_LEVELDB_FDS 0
151
151
#else
152
- #define MIN_CORE_FILEDESCRIPTORS 150
152
+ #define MIN_LEVELDB_FDS 150
153
153
#endif
154
154
155
+ static constexpr int MIN_CORE_FDS = MIN_LEVELDB_FDS + NUM_FDS_MESSAGE_CAPTURE;
155
156
static const char * DEFAULT_ASMAP_FILENAME=" ip_asn.map" ;
156
157
157
158
/* *
@@ -834,8 +835,7 @@ void InitLogging(const ArgsManager& args)
834
835
namespace { // Variables internal to initialization process only
835
836
836
837
int nMaxConnections;
837
- int nUserMaxConnections;
838
- int nFD;
838
+ int available_fds;
839
839
ServiceFlags nLocalServices = ServiceFlags(NODE_NETWORK_LIMITED | NODE_WITNESS);
840
840
int64_t peer_connect_timeout;
841
841
std::set<BlockFilterType> g_enabled_filter_types;
@@ -987,25 +987,31 @@ bool AppInitParameterInteraction(const ArgsManager& args)
987
987
return InitError (Untranslated (" Cannot set -listen=0 together with -listenonion=1" ));
988
988
}
989
989
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
994
992
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);
996
1003
// If we are using select instead of poll, our actual limit may be even smaller
997
1004
#ifndef USE_POLL
998
- nFD = std::min (FD_SETSIZE, nFD );
1005
+ available_fds = std::min (FD_SETSIZE, available_fds );
999
1006
#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 ));
1002
1009
1003
1010
// 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);
1006
1012
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));
1009
1015
1010
1016
// ********************************************************* Step 3: parameter-to-internal-flags
1011
1017
if (auto result{init::SetLoggingCategories (args)}; !result) return InitError (util::ErrorString (result));
@@ -1153,7 +1159,7 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info)
1153
1159
return false ;
1154
1160
}
1155
1161
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 );
1157
1163
1158
1164
// Warn about relative -datadir path.
1159
1165
if (args.IsArgSet (" -datadir" ) && !args.GetPathArg (" -datadir" ).is_absolute ()) {
0 commit comments