diff options
author | Zbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl> | 2021-11-02 18:18:21 +0100 |
---|---|---|
committer | Zbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl> | 2021-11-03 09:36:08 +0100 |
commit | c3dead53d50e334f2d072a2248256983d6dc9f8c (patch) | |
tree | 2926cf5000538c86ae1f221328eeac49523919e5 /src/basic/procfs-util.c | |
parent | db2aef5a1d95cea835d2a76db6da266cc4af61d6 (diff) | |
download | systemd-c3dead53d50e334f2d072a2248256983d6dc9f8c.tar.gz |
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.
Diffstat (limited to 'src/basic/procfs-util.c')
-rw-r--r-- | src/basic/procfs-util.c | 53 |
1 files changed, 13 insertions, 40 deletions
diff --git a/src/basic/procfs-util.c b/src/basic/procfs-util.c index 688c0004ea..65f96abb06 100644 --- a/src/basic/procfs-util.c +++ b/src/basic/procfs-util.c @@ -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); +} - value = mfree(value); - r = read_one_line_file("/proc/sys/kernel/threads-max", &value); - if (r < 0) - return r; +int procfs_get_threads_max(uint64_t *ret) { + _cleanup_free_ char *value = NULL; + int r; - r = safe_atou64(value, &threads_max); + assert(ret); + + r = read_one_line_file("/proc/sys/kernel/threads-max", &value); 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) - return r; /* return original error */ - - if (safe_atou64(value, &threads_max) < 0) + if (procfs_get_threads_max(&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. */ |