procfs-util: fix confusion wrt. quantity limit and maximum value
From packit/rawhide-arm64 logs: Assertion 'limit >= INT_MAX || get_process_ppid(limit+1, NULL) == -ESRCH' failed at src/test/test-process-util.c:855, function test_get_process_ppid(). Aborting. ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――― The kernel has a few different limits. In particular kernel.threads-max can be set to some lower value, and kernel.pid_max can be set to a higher value. This is nice because it reduces PID reuse, even if the number of threads that is allowed is limited. But the tests assumed that we cannot have a thread with PID above MIN(kernel.threads-max, kernel.pid_max-1), which is not valid. So let's rework the whole thing: let's expose the helpers to read kernel.threads-max and kernel.pid_max, and print what they return in tests. procfs_tasks_get_limit() was something that is only used in tests, and wasn't very well defined, so let's drop it. Fixes #21193.
This commit is contained in:
+13
-40
@@ -13,54 +13,34 @@
|
||||
#include "stdio-util.h"
|
||||
#include "string-util.h"
|
||||
|
||||
int procfs_tasks_get_limit(uint64_t *ret) {
|
||||
int procfs_get_pid_max(uint64_t *ret) {
|
||||
_cleanup_free_ char *value = NULL;
|
||||
uint64_t pid_max, threads_max;
|
||||
int r;
|
||||
|
||||
assert(ret);
|
||||
|
||||
/* So there are two sysctl files that control the system limit of processes:
|
||||
*
|
||||
* 1. kernel.threads-max: this is probably the sysctl that makes more sense, as it directly puts a limit on
|
||||
* concurrent tasks.
|
||||
*
|
||||
* 2. kernel.pid_max: this limits the numeric range PIDs can take, and thus indirectly also limits the number
|
||||
* of concurrent threads. AFAICS it's primarily a compatibility concept: some crappy old code used a signed
|
||||
* 16bit type for PIDs, hence the kernel provides a way to ensure the PIDs never go beyond INT16_MAX by
|
||||
* default.
|
||||
*
|
||||
* By default #2 is set to much lower values than #1, hence the limit people come into contact with first, as
|
||||
* it's the lowest boundary they need to bump when they want higher number of processes.
|
||||
*
|
||||
* Also note the weird definition of #2: PIDs assigned will be kept below this value, which means the number of
|
||||
* tasks that can be created is one lower, as PID 0 is not a valid process ID. */
|
||||
|
||||
r = read_one_line_file("/proc/sys/kernel/pid_max", &value);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = safe_atou64(value, &pid_max);
|
||||
if (r < 0)
|
||||
return r;
|
||||
return safe_atou64(value, ret);
|
||||
}
|
||||
|
||||
int procfs_get_threads_max(uint64_t *ret) {
|
||||
_cleanup_free_ char *value = NULL;
|
||||
int r;
|
||||
|
||||
assert(ret);
|
||||
|
||||
value = mfree(value);
|
||||
r = read_one_line_file("/proc/sys/kernel/threads-max", &value);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = safe_atou64(value, &threads_max);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
/* Subtract one from pid_max, since PID 0 is not a valid PID */
|
||||
*ret = MIN(pid_max-1, threads_max);
|
||||
return 0;
|
||||
return safe_atou64(value, ret);
|
||||
}
|
||||
|
||||
int procfs_tasks_set_limit(uint64_t limit) {
|
||||
char buffer[DECIMAL_STR_MAX(uint64_t)+1];
|
||||
_cleanup_free_ char *value = NULL;
|
||||
uint64_t pid_max;
|
||||
int r;
|
||||
|
||||
@@ -75,10 +55,7 @@ int procfs_tasks_set_limit(uint64_t limit) {
|
||||
* set it to the maximum. */
|
||||
limit = CLAMP(limit, 20U, TASKS_MAX);
|
||||
|
||||
r = read_one_line_file("/proc/sys/kernel/pid_max", &value);
|
||||
if (r < 0)
|
||||
return r;
|
||||
r = safe_atou64(value, &pid_max);
|
||||
r = procfs_get_pid_max(&pid_max);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
@@ -99,14 +76,10 @@ int procfs_tasks_set_limit(uint64_t limit) {
|
||||
/* Hmm, we couldn't write this? If so, maybe it was already set properly? In that case let's not
|
||||
* generate an error */
|
||||
|
||||
value = mfree(value);
|
||||
if (read_one_line_file("/proc/sys/kernel/threads-max", &value) < 0)
|
||||
if (procfs_get_threads_max(&threads_max) < 0)
|
||||
return r; /* return original error */
|
||||
|
||||
if (safe_atou64(value, &threads_max) < 0)
|
||||
return r; /* return original error */
|
||||
|
||||
if (MIN(pid_max-1, threads_max) != limit)
|
||||
if (MIN(pid_max - 1, threads_max) != limit)
|
||||
return r; /* return original error */
|
||||
|
||||
/* Yay! Value set already matches what we were trying to set, hence consider this a success. */
|
||||
|
||||
Reference in New Issue
Block a user