Commit 391ed084 authored by jan.koester's avatar jan.koester
Browse files

rlimit

parent 3d1b6fa9
Loading
Loading
Loading
Loading
+35 −0
Original line number Diff line number Diff line
@@ -70,6 +70,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <pwd.h>
#include <grp.h>
#include <dlfcn.h>
#include <sys/resource.h>
#endif

#include "session.h"
@@ -3793,6 +3794,36 @@ void logFiles(const char *path, int fd)
    close(pfd);
}

// Raises this process's open-file ceiling while still root -- only root/CAP_SYS_RESOURCE can
// raise rlim_max past its current value, and every worker below (the daemonize fork, each
// per-domain fork in the pre-fork supervisor, the single-domain fork) inherits whatever is set
// here via fork() rather than dropping privileges of its own, so doing this once up front in
// main() before any of those forks covers all of them. HttpConD's later seteuid()/setegid()
// only lowers the *effective* uid -- it doesn't need to happen first for this to work. Never
// fatal: a process that can't raise its own ceiling should still try to run at whatever it's
// got, not refuse to start. cfg.getmaxopenfiles() == 0 opts out entirely (leaves the OS/login-
// class default alone).
static void raiseFileDescriptorLimit(const blogi::Config &cfg)
{
    if (getuid() != 0 || cfg.getmaxopenfiles() <= 0)
        return;
    struct rlimit rl;
    if (getrlimit(RLIMIT_NOFILE, &rl) != 0)
    {
        std::cerr << "WARNING: getrlimit(RLIMIT_NOFILE) failed: " << strerror(errno) << std::endl;
        return;
    }
    rlim_t want = static_cast<rlim_t>(cfg.getmaxopenfiles());
    if (rl.rlim_max < want)
        rl.rlim_max = want;
    rl.rlim_cur = std::min(want, rl.rlim_max);
    if (setrlimit(RLIMIT_NOFILE, &rl) != 0)
    {
        std::cerr << "WARNING: setrlimit(RLIMIT_NOFILE, " << rl.rlim_cur << ") failed: "
                   << strerror(errno) << std::endl;
    }
}

static std::string stripConfigPrefix(const std::string &configPath)
{
    if (configPath.rfind("yaml:", 0) == 0)
@@ -3884,6 +3915,10 @@ int main(int argc, char *argv[])

    blogi::Blogi::Cfg = std::make_unique<blogi::Config>(config);

#ifndef _WIN32
    raiseFileDescriptorLimit(*blogi::Blogi::Cfg);
#endif

    try
    {
        struct sigaction SignalAction = {0};
+9 −0
Original line number Diff line number Diff line
@@ -41,6 +41,11 @@ blogi::Config::Config(const std::string &path) : confplus::Config(path), _Config
    } catch (...) {
        _MaxCon = -1;
    }
    try {
        _MaxOpenFiles = getIntValue(getKey("/BLOGI/MAXOPENFILES"), 0);
    } catch (...) {
        _MaxOpenFiles = 65536;
    }
    try { _HttpUrl=getValue(getKey("/BLOGI/HTTP/URL"),0); } catch(...) {}
    try {
        auto *urlKey = getKey("/BLOGI/HTTP/URL");
@@ -248,6 +253,10 @@ int blogi::Config::gethttpmaxcon() const {
    return _MaxCon;
}

int blogi::Config::getmaxopenfiles() const {
    return _MaxOpenFiles;
}

const std::string & blogi::Config::getsiteurl() const {
    return _HttpUrl;
}
+8 −0
Original line number Diff line number Diff line
@@ -117,6 +117,13 @@ namespace blogi {
        const std::string &gethttpaddr() const;
        int               gethttpmaxcon() const;

        // Raised via setrlimit(RLIMIT_NOFILE, ...) while still root, before any of main()'s
        // forked workers start (see blogi.cpp's raiseFileDescriptorLimit()). Needs to cover
        // every fd this process holds at once across every worker: per-client HTTP/HTTPS
        // sockets, authdb/mediadb connections, and each domain's own DB pool. 0 = leave the
        // OS/login-class default alone.
        int               getmaxopenfiles() const;

        const std::string &getsslcertpath() const;
        const std::string &getsslkeypath() const;
        const std::string &getsslpassword() const;
@@ -156,6 +163,7 @@ namespace blogi {
        std::string               _HttpBind;
        int                       _HttpPort;
        int                       _MaxCon;
        int                       _MaxOpenFiles;
        std::string               _HttpUrl;
        std::vector<std::string>  _HttpUrls;
        std::string               _HttpPrefix;