wayland: Bump RLIMIT_NOFILE limit

As a wayland compositor kwin can hold many open file descriptors and
therefore it's easier for it to hit the soft file descriptor limit. This
change makes kwin_wayland bump the soft file descriptor limit to the
hard limit. With systemd, it's usually 500K.

In order to prevent causing mess in child processes, pthread_atfork() is
used to register a handler which will be invoked in the child process
after fork() in order to restore RLIMIT_NOFILE to its original value.
This commit is contained in:
Vlad Zahorodnii 2022-05-15 16:22:35 +03:00
parent 2178f26e7b
commit ed90be0783

View file

@ -43,6 +43,7 @@
#endif
#include <sched.h>
#include <sys/resource.h>
#include <iomanip>
#include <iostream>
@ -58,6 +59,36 @@ Q_IMPORT_PLUGIN(ScreencastManagerFactory)
namespace KWin
{
static rlimit originalNofileLimit = {
.rlim_cur = 0,
.rlim_max = 0,
};
static bool bumpNofileLimit()
{
if (getrlimit(RLIMIT_NOFILE, &originalNofileLimit) == -1) {
std::cerr << "Failed to bump RLIMIT_NOFILE limit, getrlimit() failed: " << strerror(errno) << std::endl;
return false;
}
rlimit limit = originalNofileLimit;
limit.rlim_cur = limit.rlim_max;
if (setrlimit(RLIMIT_NOFILE, &limit) == -1) {
std::cerr << "Failed to bump RLIMIT_NOFILE limit, setrlimit() failed: " << strerror(errno) << std::endl;
return false;
}
return true;
}
static void restoreNofileLimit()
{
if (setrlimit(RLIMIT_NOFILE, &originalNofileLimit) == -1) {
std::cerr << "Failed to restore RLIMIT_NOFILE limit, legacy apps might be broken" << std::endl;
}
}
static void sighandler(int)
{
QApplication::exit();
@ -322,6 +353,13 @@ int main(int argc, char *argv[])
}
signal(SIGPIPE, SIG_IGN);
// It's easy to exceed the file descriptor limit because many things are backed using fds
// nowadays, e.g. dmabufs, shm buffers, etc. Bump the RLIMIT_NOFILE limit to handle that.
// Some apps may still use select(), so we reset the limit to its original value in fork().
if (KWin::bumpNofileLimit()) {
pthread_atfork(nullptr, nullptr, KWin::restoreNofileLimit);
}
QProcessEnvironment environment = QProcessEnvironment::systemEnvironment();
// enforce our internal qpa plugin, unfortunately command line switch has precedence