sslbd/fdtable.cpp
#include "fdtable.hpp"
#include <unistd.h>
#include <dirent.h>
#include <sys/resource.h>
HOOK(INIT, HOOK_PRIO_MID) { ///< adjusts fdlimit according to FdTable::size
const rlim_t lim = FdTable<int>::size;
struct rlimit rlim;
if (getrlimit(RLIMIT_NOFILE, &rlim) == -1) {
log_errno(error, "getrlimit(NOFILE)");
return;
}
log(debug, "getrlimit(RLIMIT_NOFILE): %lu/%lu (%lu)", rlim.rlim_cur, rlim.rlim_max, lim);
// decrease or un-priviledged increase?
if (rlim.rlim_cur > lim || rlim.rlim_max >= lim) {
rlim.rlim_cur = lim;
if (setrlimit(RLIMIT_NOFILE, &rlim) == -1) {
log_errno(error, "setrlimit(NOFILE,%lu,%lu)", lim, rlim.rlim_max);
}
return;
}
// need priviledged increase
rlim.rlim_cur = lim;
rlim.rlim_max = lim;
if (setrlimit(RLIMIT_NOFILE, &rlim) == -1) {
log_errno(error, "setrlimit(NOFILE,%lu)", lim);
}
}
int get_maxfd() {
return getdtablesize(); // TODO: should we cache this?
}
int get_curr_maxfd() {
// https://github.com/openssh/openssh-portable/blob/master/openbsd-compat/bsd-closefrom.c
// https://git.gnome.org/browse/glib/tree/gio/libasyncns/asyncns.c?h=2.21.0#n205
DIR* dirp = opendir("/proc/self/fd");
unless (dirp) {
log_errno(error, "opendir(/proc/self/fd)");
return get_maxfd();
}
int maxfd = -1;
struct dirent* dent;
while ((dent = readdir(dirp)) != NULL) {
int fd = atoi(dent->d_name);
if (fd >= 0 && fd > maxfd && fd != dirfd(dirp)) {
maxfd = fd;
}
}
closedir(dirp);
++maxfd;
#ifdef DEBUG
if (is_valgrind()) {
return MIN(maxfd, get_maxfd());
} else {
assert(maxfd <= get_maxfd());
}
#endif
return maxfd;
}