mirror of
https://gitlab.freedesktop.org/pipewire/pipewire.git
synced 2025-10-29 05:40:27 -04:00
context: add support for rlimit.<resource> = <value>
Add support for rlimit.<resource> = <value> in the context.properties to adjust the rlimits of the process. A value of -1 sets the max limit. This can be used to increase the number of file descriptors in a pipewire process when select() is not used, for example. Other resource limits might be interesting as well maybe. Fixes #4047
This commit is contained in:
parent
9f2d873760
commit
9b507d3210
4 changed files with 100 additions and 0 deletions
|
|
@ -275,6 +275,20 @@ Warn about failures to lock memory.
|
||||||
@PAR@ pipewire.conf mem.mlock-all = false
|
@PAR@ pipewire.conf mem.mlock-all = false
|
||||||
Try to mlock all current and future memory by the process.
|
Try to mlock all current and future memory by the process.
|
||||||
|
|
||||||
|
@PAR@ pipewire.conf rlimit.nofile = 4096
|
||||||
|
Try to set the max file descriptor number resource limit of the process.
|
||||||
|
A value of -1 raises the limit to the system defined hard maximum value.
|
||||||
|
The file resource limit is usually 1024 and should only be raised if the
|
||||||
|
program does not use the select() system call. PipeWire does normally not
|
||||||
|
use select().
|
||||||
|
|
||||||
|
@PAR@ pipewire.conf rlimit.*resource* = *value*
|
||||||
|
Set resource limits. *resource* can be one of: as, core, cpu,
|
||||||
|
data, fsize, locks, memlock, msgqueue, nice, nofile, nproc, rss, rtprio,
|
||||||
|
rttime, sigpending or stack. See the documentation of setrlimit to get the
|
||||||
|
meaning of these resources. A value of -1 will set the maximum allowed
|
||||||
|
limit.
|
||||||
|
|
||||||
@PAR@ pipewire.conf settings.check-quantum = false
|
@PAR@ pipewire.conf settings.check-quantum = false
|
||||||
Check if the quantum in the settings metadata update is compatible
|
Check if the quantum in the settings metadata update is compatible
|
||||||
with the configured limits.
|
with the configured limits.
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,7 @@ context.properties = {
|
||||||
#mem.allow-mlock = true
|
#mem.allow-mlock = true
|
||||||
#mem.mlock-all = false
|
#mem.mlock-all = false
|
||||||
#log.level = 2
|
#log.level = 2
|
||||||
|
#rlimit.nofile = -1
|
||||||
|
|
||||||
#default.clock.quantum-limit = 8192
|
#default.clock.quantum-limit = 8192
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,7 @@ context.properties = {
|
||||||
#clock.power-of-two-quantum = true
|
#clock.power-of-two-quantum = true
|
||||||
#log.level = 2
|
#log.level = 2
|
||||||
#cpu.zero.denormals = false
|
#cpu.zero.denormals = false
|
||||||
|
#rlimit.nofile = -1
|
||||||
|
|
||||||
#loop.rt-prio = -1 # -1 = use module-rt prio, 0 disable rt
|
#loop.rt-prio = -1 # -1 = use module-rt prio, 0 disable rt
|
||||||
#loop.class = data.rt
|
#loop.class = data.rt
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,7 @@
|
||||||
#include <regex.h>
|
#include <regex.h>
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
#include <sys/mman.h>
|
#include <sys/mman.h>
|
||||||
|
#include <sys/resource.h>
|
||||||
#include <fnmatch.h>
|
#include <fnmatch.h>
|
||||||
|
|
||||||
#include <pipewire/log.h>
|
#include <pipewire/log.h>
|
||||||
|
|
@ -300,6 +301,88 @@ static void data_loop_stop(struct impl *impl, struct data_loop *loop)
|
||||||
loop->started = false;
|
loop->started = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int adjust_rlimit(int resource, const char *name, int value)
|
||||||
|
{
|
||||||
|
struct rlimit rlim, highest, fixed;
|
||||||
|
|
||||||
|
rlim = (struct rlimit) { .rlim_cur = value, .rlim_max = value, };
|
||||||
|
|
||||||
|
if (setrlimit(resource, &rlim) >= 0) {
|
||||||
|
pw_log_info("set rlimit %s to %d", name, value);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (errno != EPERM)
|
||||||
|
return -errno;
|
||||||
|
|
||||||
|
/* So we failed to set the desired setrlimit, then let's try
|
||||||
|
* to get as close as we can */
|
||||||
|
if (getrlimit(resource, &highest) < 0)
|
||||||
|
return -errno;
|
||||||
|
|
||||||
|
/* If the hard limit is unbounded anyway, then the EPERM had other reasons,
|
||||||
|
* let's propagate the original EPERM then */
|
||||||
|
if (highest.rlim_max == RLIM_INFINITY)
|
||||||
|
return -EPERM;
|
||||||
|
|
||||||
|
fixed = (struct rlimit) {
|
||||||
|
.rlim_cur = SPA_MIN(rlim.rlim_cur, highest.rlim_max),
|
||||||
|
.rlim_max = SPA_MIN(rlim.rlim_max, highest.rlim_max),
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Shortcut things if we wouldn't change anything. */
|
||||||
|
if (fixed.rlim_cur == highest.rlim_cur &&
|
||||||
|
fixed.rlim_max == highest.rlim_max)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
pw_log_info("set rlimit %s to %d/%d instead of %d", name,
|
||||||
|
(int)fixed.rlim_cur, (int)fixed.rlim_max, value);
|
||||||
|
if (setrlimit(resource, &fixed) < 0)
|
||||||
|
return -errno;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int adjust_rlimits(const struct spa_dict *dict)
|
||||||
|
{
|
||||||
|
const struct spa_dict_item *it;
|
||||||
|
static const char* rlimit_table[] = {
|
||||||
|
[RLIMIT_AS] = "as",
|
||||||
|
[RLIMIT_CORE] = "core",
|
||||||
|
[RLIMIT_CPU] = "cpu",
|
||||||
|
[RLIMIT_DATA] = "data",
|
||||||
|
[RLIMIT_FSIZE] = "fsize",
|
||||||
|
[RLIMIT_LOCKS] = "locks",
|
||||||
|
[RLIMIT_MEMLOCK] = "memlock",
|
||||||
|
[RLIMIT_MSGQUEUE] = "msgqueue",
|
||||||
|
[RLIMIT_NICE] = "nice",
|
||||||
|
[RLIMIT_NOFILE] = "nofile",
|
||||||
|
[RLIMIT_NPROC] = "nproc",
|
||||||
|
[RLIMIT_RSS] = "rss",
|
||||||
|
[RLIMIT_RTPRIO] = "rtprio",
|
||||||
|
[RLIMIT_RTTIME] = "rttime",
|
||||||
|
[RLIMIT_SIGPENDING] = "sigpending",
|
||||||
|
[RLIMIT_STACK] = "stack",
|
||||||
|
};
|
||||||
|
int res;
|
||||||
|
spa_dict_for_each(it, dict) {
|
||||||
|
if (!spa_strstartswith(it->key, "rlimit."))
|
||||||
|
continue;
|
||||||
|
for (size_t i = 0; i < SPA_N_ELEMENTS(rlimit_table); i++) {
|
||||||
|
const char *name = rlimit_table[i];
|
||||||
|
int64_t val;
|
||||||
|
if (!spa_streq(it->key+7, name))
|
||||||
|
continue;
|
||||||
|
if (!spa_atoi64(it->value, &val, 0)) {
|
||||||
|
pw_log_warn("invalid number %s", it->value);
|
||||||
|
} else if ((res = adjust_rlimit(i, name, val)) < 0)
|
||||||
|
pw_log_warn("can't set rlimit %s to %s: %s",
|
||||||
|
name, it->value, spa_strerror(res));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/** Create a new context object
|
/** Create a new context object
|
||||||
*
|
*
|
||||||
* \param main_loop the main loop to use
|
* \param main_loop the main loop to use
|
||||||
|
|
@ -420,6 +503,7 @@ struct pw_context *pw_context_new(struct pw_loop *main_loop,
|
||||||
else
|
else
|
||||||
pw_log_info("%p: mlockall succeeded", impl);
|
pw_log_info("%p: mlockall succeeded", impl);
|
||||||
}
|
}
|
||||||
|
adjust_rlimits(&properties->dict);
|
||||||
|
|
||||||
pw_settings_init(this);
|
pw_settings_init(this);
|
||||||
this->settings = this->defaults;
|
this->settings = this->defaults;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue