diff --git a/src/init.cpp b/src/init.cpp index d280ef905a1..39abea3895c 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -147,11 +147,12 @@ static constexpr bool DEFAULT_STOPAFTERBLOCKIMPORT{false}; // Win32 LevelDB doesn't use filedescriptors, and the ones used for // accessing block files don't count towards the fd_set size limit // anyway. -#define MIN_CORE_FILEDESCRIPTORS 0 +#define MIN_LEVELDB_FDS 0 #else -#define MIN_CORE_FILEDESCRIPTORS 150 +#define MIN_LEVELDB_FDS 150 #endif +static constexpr int MIN_CORE_FDS = MIN_LEVELDB_FDS + NUM_FDS_MESSAGE_CAPTURE; static const char* DEFAULT_ASMAP_FILENAME="ip_asn.map"; /** @@ -834,8 +835,7 @@ void InitLogging(const ArgsManager& args) namespace { // Variables internal to initialization process only int nMaxConnections; -int nUserMaxConnections; -int nFD; +int available_fds; ServiceFlags nLocalServices = ServiceFlags(NODE_NETWORK_LIMITED | NODE_WITNESS); int64_t peer_connect_timeout; std::set g_enabled_filter_types; @@ -987,25 +987,31 @@ bool AppInitParameterInteraction(const ArgsManager& args) return InitError(Untranslated("Cannot set -listen=0 together with -listenonion=1")); } - // Make sure enough file descriptors are available - int nBind = std::max(nUserBind, size_t(1)); - nUserMaxConnections = args.GetIntArg("-maxconnections", DEFAULT_MAX_PEER_CONNECTIONS); - nMaxConnections = std::max(nUserMaxConnections, 0); + // Make sure enough file descriptors are available. We need to reserve enough FDs to account for the bare minimum, + // plus all manual connections and all bound interfaces. Any remainder will be available for connection sockets - nFD = RaiseFileDescriptorLimit(nMaxConnections + MIN_CORE_FILEDESCRIPTORS + MAX_ADDNODE_CONNECTIONS + nBind + NUM_FDS_MESSAGE_CAPTURE); + // Number of bound interfaces (we have at least one) + int nBind = std::max(nUserBind, size_t(1)); + // Maximum number of connections with other nodes, this accounts for all types of outbounds and inbounds except for manual + int user_max_connection = args.GetIntArg("-maxconnections", DEFAULT_MAX_PEER_CONNECTIONS); + nMaxConnections = std::max(user_max_connection, 0); + // Reserve enough FDs to account for the bare minimum, plus any manual connections, plus the bound interfaces + int min_required_fds = MIN_CORE_FDS + MAX_ADDNODE_CONNECTIONS + nBind; + + // Try raising the FD limit to what we need (available_fds may be smaller than the requested amount if this fails) + available_fds = RaiseFileDescriptorLimit(nMaxConnections + min_required_fds); // If we are using select instead of poll, our actual limit may be even smaller #ifndef USE_POLL - nFD = std::min(FD_SETSIZE, nFD); + available_fds = std::min(FD_SETSIZE, available_fds); #endif - if (nFD < MIN_CORE_FILEDESCRIPTORS) - return InitError(_("Not enough file descriptors available.")); + if (available_fds < min_required_fds) + return InitError(strprintf(_("Not enough file descriptors available. %d available, %d required."), available_fds, min_required_fds)); // Trim requested connection counts, to fit into system limitations - // in std::min(...) to work around FreeBSD compilation issue described in #2695 - nMaxConnections = std::max(std::min(nMaxConnections, nFD - nBind - MIN_CORE_FILEDESCRIPTORS - MAX_ADDNODE_CONNECTIONS - NUM_FDS_MESSAGE_CAPTURE), 0); + nMaxConnections = std::min(available_fds - min_required_fds, nMaxConnections); - if (nMaxConnections < nUserMaxConnections) - InitWarning(strprintf(_("Reducing -maxconnections from %d to %d, because of system limitations."), nUserMaxConnections, nMaxConnections)); + if (nMaxConnections < user_max_connection) + InitWarning(strprintf(_("Reducing -maxconnections from %d to %d, because of system limitations."), user_max_connection, nMaxConnections)); // ********************************************************* Step 3: parameter-to-internal-flags if (auto result{init::SetLoggingCategories(args)}; !result) return InitError(util::ErrorString(result)); @@ -1153,7 +1159,7 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info) return false; } - LogPrintf("Using at most %i automatic connections (%i file descriptors available)\n", nMaxConnections, nFD); + LogPrintf("Using at most %i automatic connections (%i file descriptors available)\n", nMaxConnections, available_fds); // Warn about relative -datadir path. if (args.IsArgSet("-datadir") && !args.GetPathArg("-datadir").is_absolute()) {