From 34979250004fb2785ed68c9714a42ddef6523a90 Mon Sep 17 00:00:00 2001 From: Alexander Barton Date: Thu, 28 Mar 2024 10:16:44 +0100 Subject: [PATCH] Try to set file descriptor limit to its maximum and show info on startup The number of possible parallel connections is limited by the process file descriptor limit (among other things). Therefore try to upgrade the current "soft" limit to its "hard" maximum (but limit it to 100000), and show an information or even warning, wenn still less than the configured "MaxConnections" setting. Please note that ngIRCd and its linked libraries (like PAM) need file descriptors not only for incoming and outgoing IRC connections, but for reading files and inter-process communication, too! Therefore the actual connection limit is _less_ than the file descriptor limit! This introduces the new MAX_FD_LIMIT (100000) #define. --- configure.ng | 2 ++ contrib/ngircd.logcheck | 1 + src/ngircd/conf.c | 50 +++++++++++++++++++++++++++++++++++++++++ src/ngircd/defines.h | 5 ++++- 4 files changed, 57 insertions(+), 1 deletion(-) diff --git a/configure.ng b/configure.ng index f6c70e5d..ec7b6c35 100644 --- a/configure.ng +++ b/configure.ng @@ -192,6 +192,7 @@ AC_CHECK_HEADERS_ONCE([ \ stdbool.h \ stddef.h \ stdint.h \ + sys/resource.h \ varargs.h \ ]) @@ -274,6 +275,7 @@ AC_CHECK_FUNCS_ONCE([ getnameinfo \ inet_aton \ setgroups \ + setrlimit \ sigaction \ sigprocmask \ snprintf \ diff --git a/contrib/ngircd.logcheck b/contrib/ngircd.logcheck index 1224551f..905162d6 100644 --- a/contrib/ngircd.logcheck +++ b/contrib/ngircd.logcheck @@ -12,6 +12,7 @@ ^\w{3} [ :0-9]{11} [._[:alnum:]-]+ ngircd\[[0-9]+\]: Deleted ".*" \(".*"\) from G-Line list \(expired\)\.$ ^\w{3} [ :0-9]{11} [._[:alnum:]-]+ ngircd\[[0-9]+\]: Enabled link compression \(zlib\) on connection [0-9]+\.$ ^\w{3} [ :0-9]{11} [._[:alnum:]-]+ ngircd\[[0-9]+\]: Establishing connection for ".*" to ".*:[0-9]+" \(.*\), socket [0-9]+ \.\.\.$ +^\w{3} [ :0-9]{11} [._[:alnum:]-]+ ngircd\[[0-9]+\]: File descriptor limit is [0-9]+; "MaxConnections" is (not set|set to [0-9]+)\.$ ^\w{3} [ :0-9]{11} [._[:alnum:]-]+ ngircd\[[0-9]+\]: Got (valid server|unchecked peer) certificate: .*\.$ ^\w{3} [ :0-9]{11} [._[:alnum:]-]+ ngircd\[[0-9]+\]: Got signal "(Hangup|Terminated)" \.\.\.$ ^\w{3} [ :0-9]{11} [._[:alnum:]-]+ ngircd\[[0-9]+\]: Got valid OPER for ".*" from ".*", user is an IRC operator now\.$ diff --git a/src/ngircd/conf.c b/src/ngircd/conf.c index 441b8f67..e4cd8963 100644 --- a/src/ngircd/conf.c +++ b/src/ngircd/conf.c @@ -35,6 +35,10 @@ #include #include +#ifdef HAVE_SYS_RESOURCE_H +# include +#endif + #include "ngircd.h" #include "conn.h" #include "channel.h" @@ -2108,6 +2112,10 @@ Validate_Config(bool Configtest, bool Rehash) struct hostent *h; bool config_valid = true; char *ptr; +#ifdef HAVE_SETRLIMIT + struct rlimit rlim; + long fd_lim_old; +#endif /* Emit a warning when the config file is not a full path name */ if (NGIRCd_ConfFile[0] && NGIRCd_ConfFile[0] != '/') { @@ -2197,6 +2205,48 @@ Validate_Config(bool Configtest, bool Rehash) "Maximum penalty increase ('MaxPenaltyTime') is set to %ld, this is not recommended!", Conf_MaxPenaltyTime); +#ifdef HAVE_SETRLIMIT + if(getrlimit(RLIMIT_NOFILE, &rlim) == 0) { + LogDebug("Current file descriptor limit is %ld, maximum %ld. \"MaxConnections\" is %ld.", + (long)rlim.rlim_cur, (long)rlim.rlim_max, + Conf_MaxConnections); + fd_lim_old = rlim.rlim_cur; + /* Don't request "infinite" file descriptors, use a limit! */ + if (rlim.rlim_max != RLIM_INFINITY && rlim.rlim_max < MAX_FD_LIMIT) + rlim.rlim_cur = rlim.rlim_max; + else + rlim.rlim_cur = MAX_FD_LIMIT; + if ((long)rlim.rlim_cur != fd_lim_old) { + /* Try to adjust the current file descriptor limit: */ + LogDebug("Trying to upgrade \"soft\" file descriptor limit: %ld -> %ld ...", + fd_lim_old, (long)rlim.rlim_cur); + if(setrlimit(RLIMIT_NOFILE, &rlim) != 0) + Config_Error(LOG_ERR, "Failed to adjust file descriptor limit from %ld to %ld: %s", + fd_lim_old, (long)rlim.rlim_cur, + strerror(errno)); + } + /* Check the (updated?) file descriptor limit: */ + getrlimit(RLIMIT_NOFILE, &rlim); + if (rlim.rlim_cur != RLIM_INFINITY + && (long)rlim.rlim_cur <= (long)Conf_MaxConnections) { + Config_Error(LOG_WARNING, + "Current file descriptor limit (%ld) is not higher than configured \"MaxConnections\" (%ld)!", + (long)rlim.rlim_cur, Conf_MaxConnections); + } else if (!Configtest) { + if (Conf_MaxConnections > 0) + Log(LOG_INFO, + "File descriptor limit is %ld; \"MaxConnections\" is set to %ld.", + (long)rlim.rlim_cur, Conf_MaxConnections); + else + Log(LOG_INFO, + "File descriptor limit is %ld; \"MaxConnections\" is not set.", + (long)rlim.rlim_cur); + } + } else + Config_Error(LOG_ERR, "Failed to get file descriptor limit: %s", + strerror(errno)); +#endif + servers = servers_once = 0; for (i = 0; i < MAX_SERVERS; i++) { if (Conf_Server[i].name[0]) { diff --git a/src/ngircd/defines.h b/src/ngircd/defines.h index 0b44a5b4..e3df44b9 100644 --- a/src/ngircd/defines.h +++ b/src/ngircd/defines.h @@ -1,6 +1,6 @@ /* * ngIRCd -- The Next Generation IRC Daemon - * Copyright (c)2001-2014 Alexander Barton (alex@barton.de) and Contributors. + * Copyright (c)2001-2024 Alexander Barton (alex@barton.de) and Contributors. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -64,6 +64,9 @@ /** Size of buffer for PAM service name. */ #define MAX_PAM_SERVICE_NAME_LEN 64 +/** Maximum number of file descriptors to request. */ +#define MAX_FD_LIMIT 100000 + /* Hard-coded (default) options */ -- 2.39.2