summaryrefslogtreecommitdiff
path: root/src/basic/procfs-util.c
diff options
context:
space:
mode:
authorZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>2021-11-02 18:18:21 +0100
committerZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>2021-11-03 09:36:08 +0100
commitc3dead53d50e334f2d072a2248256983d6dc9f8c (patch)
tree2926cf5000538c86ae1f221328eeac49523919e5 /src/basic/procfs-util.c
parentdb2aef5a1d95cea835d2a76db6da266cc4af61d6 (diff)
downloadsystemd-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.c53
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. */