mirror of
https://github.com/robbert-vdh/yabridge.git
synced 2026-05-07 03:50:11 +02:00
Warn on startup if RLIMIT_MEMLOCK is set too low
This should diagnose issues like #119.
This commit is contained in:
@@ -14,6 +14,8 @@ Versioning](https://semver.org/spec/v2.0.0.html).
|
||||
shared memory. If you have not yet set up realtime priviliges and memory
|
||||
locking limits for your user, then yabridge may not be able to map enough
|
||||
shared memory for processing audio in plugins with a lot of inputs or outputs.
|
||||
- Also added a warning for thisq in the initialization message if yabridge
|
||||
detects a low value for `RLIMIT_MEMLOCK`.
|
||||
|
||||
### Fixed
|
||||
|
||||
|
||||
@@ -57,6 +57,15 @@ bool set_realtime_priority(bool sched_fifo, int priority) noexcept {
|
||||
¶ms) == 0;
|
||||
}
|
||||
|
||||
std::optional<rlim_t> get_memlock_limit() noexcept {
|
||||
rlimit limits{};
|
||||
if (getrlimit(RLIMIT_MEMLOCK, &limits) == 0) {
|
||||
return limits.rlim_cur;
|
||||
} else {
|
||||
return std::nullopt;
|
||||
}
|
||||
}
|
||||
|
||||
std::optional<rlim_t> get_rttime_limit() noexcept {
|
||||
rlimit limits{};
|
||||
if (getrlimit(RLIMIT_RTTIME, &limits) == 0) {
|
||||
|
||||
+13
-4
@@ -106,10 +106,19 @@ std::optional<int> get_realtime_priority() noexcept;
|
||||
bool set_realtime_priority(bool sched_fifo, int priority = 5) noexcept;
|
||||
|
||||
/**
|
||||
* Get the (soft) `RTTIME` resource limit, or the amount of time a `SCHED_FIFO`
|
||||
* process may spend uninterrupted before being killed by the scheduler. A value
|
||||
* of `-1`/`RLIM_INFINITY` means that there is no limit. If there was some error
|
||||
* fetching this value, then a nullopt will be returned.
|
||||
* Get the (soft) `RLIMIT_MEMLOCK` resource limit. If this is set to some low
|
||||
* value, then we'll print a warning during initialization because mapping
|
||||
* shared memory may fail. A value of `-1`/`RLIM_INFINITY` means that there is
|
||||
* no limit. If there was some error fetching this value, then a nullopt will be
|
||||
* returned.
|
||||
*/
|
||||
std::optional<rlim_t> get_memlock_limit() noexcept;
|
||||
|
||||
/**
|
||||
* Get the (soft) `RLIMIT_RTTIME` resource limit, or the amount of time a
|
||||
* `SCHED_FIFO` process may spend uninterrupted before being killed by the
|
||||
* scheduler. A value of `-1`/`RLIM_INFINITY` means that there is no limit. If
|
||||
* there was some error fetching this value, then a nullopt will be returned.
|
||||
*
|
||||
* This is useful to diagnose issues caused by PipeWire. They use rtkit at the
|
||||
* moment, and both rtkit and PipeWire's rtkit module will enable a realtime CPU
|
||||
|
||||
@@ -29,6 +29,14 @@
|
||||
#include "../../common/utils.h"
|
||||
#include "../host-process.h"
|
||||
|
||||
/**
|
||||
* If the amount of lockable memory is below this, then we'll warn about it
|
||||
* during startup. Otherwise we may run into issues when mapping shared memory
|
||||
* for plugins with a lot of inputs or outputs. We would of course prefer this
|
||||
* to just be set to `RLIM_INFINITY`, but this seems like a reasonable amount.
|
||||
*/
|
||||
constexpr int memlock_min_safe_threshold = 256 << 20;
|
||||
|
||||
/**
|
||||
* PipeWire uses rtkit, and both set `RLIMIT_RTTIME` to some low value. Normally
|
||||
* this is kept at unlimited, and low values can cause the host process to get
|
||||
@@ -149,7 +157,8 @@ class PluginBridge {
|
||||
init_msg << " RLIMIT_RTTIME is set to " << *rttime_limit
|
||||
<< " us. This can happen when" << std::endl;
|
||||
init_msg << " using PipeWire. yabridge may crash when "
|
||||
<< "loading plugins" << std::endl;
|
||||
"loading plugins"
|
||||
<< std::endl;
|
||||
init_msg << " until you fix this." << std::endl;
|
||||
init_msg << std::endl;
|
||||
} else {
|
||||
@@ -162,6 +171,32 @@ class PluginBridge {
|
||||
} else {
|
||||
init_msg << "'no'" << std::endl;
|
||||
}
|
||||
// This doesn't really fit here, but this seems like the place to warn
|
||||
// about low memlock limits. Because this is meant to just be a helpful
|
||||
// warning, we won't print anything at all when there's no need to.
|
||||
if (auto memlock_limit = get_memlock_limit()) {
|
||||
if (*memlock_limit != RLIM_INFINITY &&
|
||||
*memlock_limit < memlock_min_safe_threshold) {
|
||||
init_msg << "memlock limit: 'WARNING: " << *memlock_limit
|
||||
<< " bytes, see below'" << std::endl;
|
||||
init_msg << std::endl;
|
||||
init_msg
|
||||
<< " With a low memory locking limit, yabridge may not be"
|
||||
<< std::endl;
|
||||
init_msg << " be able to map enough shared memory for audio "
|
||||
"buffers,"
|
||||
<< std::endl;
|
||||
init_msg << " yabridge may crash when using plugins with "
|
||||
"many inputs"
|
||||
<< std::endl;
|
||||
init_msg << " or outputs until you fix this." << std::endl;
|
||||
init_msg << std::endl;
|
||||
}
|
||||
} else {
|
||||
init_msg
|
||||
<< "memlock limit: 'WARNING: Could not fetch RLIMIT_MEMLOCK'"
|
||||
<< std::endl;
|
||||
}
|
||||
init_msg << "sockets: '" << sockets.base_dir.string() << "'"
|
||||
<< std::endl;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user