34#include <sys/resource.h>
39#include <sys/sysctl.h>
95namespace fd_limit_impl {
99 std::ifstream in(path);
114#if defined(__APPLE__)
116 size_t size =
sizeof(value);
117 if (sysctlbyname(
"kern.maxfilesperproc", &value, &size,
nullptr, 0) == 0 &&
119 return static_cast<uint64_t
>(value);
122#elif defined(__linux__)
143 if (getrlimit(RLIMIT_NOFILE, &rl) != 0)
146 limits.
soft =
static_cast<uint64_t
>(rl.rlim_cur);
147 limits.
hard = rl.rlim_max == RLIM_INFINITY
149 :
static_cast<uint64_t
>(rl.rlim_max);
151 limits.
hard = std::min(limits.
hard, *ceiling);
188 return std::to_string(limits.
soft) +
" soft / " + std::to_string(limits.
hard) +
195 return "set `max_open_files` in the [broker] section of the settings file "
196 "(or LimitNOFILE= in the systemd unit) to raise it";
210 if (requested.has_value()) {
211 plan.
message =
"max_open_files is not applicable on this platform: it "
212 "has no per-process descriptor limit for sockets";
220 if (!requested.has_value()) {
231 if (*requested < 0) {
236 plan.
message =
"Invalid [broker] max_open_files = " +
237 std::to_string(*requested) +
", ignoring it. File "
243 uint64_t wanted = *requested == 0 ? limits.
hard
244 :
static_cast<uint64_t
>(*requested);
250 wanted = limits.
hard;
254 if (wanted == limits.
soft) {
257 " (max_open_files already in force)";
258 }
else if (wanted > limits.
soft) {
260 plan.
message =
"File descriptors: raising soft limit " +
261 std::to_string(limits.
soft) +
" -> " +
262 std::to_string(wanted) +
" (hard " +
263 std::to_string(limits.
hard) +
"), about " +
276 plan.
message =
"File descriptors: lowering soft limit " +
277 std::to_string(limits.
soft) +
" -> " +
278 std::to_string(wanted) +
" (hard " +
279 std::to_string(limits.
hard) +
"), room for about " +
285 plan.
message +=
" -- WARNING: the broker needs about " +
287 " descriptors for itself and will most likely fail to"
288 " start with this few";
294 plan.
message +=
". max_open_files = " + std::to_string(*requested) +
295 " exceeds this process's hard limit of " +
296 std::to_string(limits.
hard) +
297 "; raising that needs LimitNOFILE= in the systemd unit or"
298 " a privileged `ulimit -Hn`";
329 if (getrlimit(RLIMIT_NOFILE, &rl) != 0) {
330 outcome.
error = std::strerror(errno);
333 rl.rlim_cur =
static_cast<rlim_t
>(plan.
target);
334 if (setrlimit(RLIMIT_NOFILE, &rl) != 0) {
335 outcome.
error = std::strerror(errno);
349 return err == EMFILE || err == 10024 ;
351 return err == EMFILE || err == ENFILE;
std::optional< uint64_t > read_uint_file(const char *path)
Reads a single unsigned integer out of a /proc or /sys file.
std::optional< uint64_t > kernel_fd_ceiling()
FdLimitOutcome apply_fd_limit(const FdLimitPlan &plan)
FdLimitPlan plan_fd_limit(std::optional< int64_t > requested, const FdLimits &limits)
constexpr uint64_t FD_PER_AGENT
constexpr uint64_t FD_BROKER_OVERHEAD
std::string describe_fd_limits(const FdLimits &limits)
Renders e.g. "1024 soft / 1048576 hard, about 492 agents".
uint64_t agent_capacity(uint64_t soft)
How many agents a given soft limit leaves room for.
FdLimits query_fd_limits()
Reads the limits currently in force, with hard clamped as described above.
constexpr uint64_t FD_LOW_WATERMARK
std::string fd_limit_hint()
The hint appended to every message that reports a limit worth raising.
constexpr uint64_t FD_ABSOLUTE_CEILING
bool is_fd_exhaustion(int err)
The result of acting on a plan.
FdLimits limits
the limits in force afterwards
std::string error
why it failed, when it did
bool applied
a setrlimit() call was made and succeeded
@ Raise
raise the soft limit to target
@ Invalid
configured value makes no sense; ignored, limit untouched
@ Unchanged
the soft limit is already exactly what was asked for
@ NotSupported
no per-process descriptor limit on this platform
@ Lower
lower the soft limit to target
@ Unset
nothing configured; report the limit and leave it alone
std::string message
One line, ready to print, explaining the limit and what was done to it.
uint64_t target
The soft limit that should end up in force.
bool warn
True when message reports something the operator should act on.