[LTP] [PATCH] syscalls/fork13: Rewrite to new API + add .max_runtime
Cyril Hrubis
chrubis@suse.cz
Thu Jun 16 15:49:19 CEST 2022
This fixes a problem we had for years, the test can run for more than
half an hour on slow systems and it used to timeout quite often.
This commit introduces a max_runtime with a 10 minute limit which is
more than enough for the test to complete on a modern hardware but at
the same time it limits the runtime to a sensible value on older
hardware and embedded.
Signed-off-by: Cyril Hrubis <chrubis@suse.cz>
---
README.md | 2 +-
runtest/syscalls | 2 +-
testcases/kernel/syscalls/fork/fork13.c | 168 ++++++++++--------------
3 files changed, 71 insertions(+), 101 deletions(-)
diff --git a/README.md b/README.md
index 7764eb81a..3a0fd7f96 100644
--- a/README.md
+++ b/README.md
@@ -150,7 +150,7 @@ $ testcases/bin/abort01
Some have arguments
```
-$ testcases/bin/fork13 -i 37
+$ testcases/bin/mesgq\_nstest -m none
```
The vast majority of test cases accept the -h (help) switch
diff --git a/runtest/syscalls b/runtest/syscalls
index 88c31db06..36fc50aeb 100644
--- a/runtest/syscalls
+++ b/runtest/syscalls
@@ -372,7 +372,7 @@ fork08 fork08
fork09 fork09
fork10 fork10
fork11 fork11
-fork13 fork13 -i 1000000
+fork13 fork13
fork14 fork14
fpathconf01 fpathconf01
diff --git a/testcases/kernel/syscalls/fork/fork13.c b/testcases/kernel/syscalls/fork/fork13.c
index 583c8bd4d..1714beff3 100644
--- a/testcases/kernel/syscalls/fork/fork13.c
+++ b/testcases/kernel/syscalls/fork/fork13.c
@@ -1,5 +1,13 @@
+// SPDX-License-Identifier: GPL-2.0
/*
- * a race in pid generation that causes pids to be reused immediately
+ * Copyright (C) 2010 Red Hat, Inc.
+ * Copyright (C) 2022 Cyril Hrubis <chrubis@suse.cz>
+ */
+
+/*\
+ * [Description]
+ *
+ * A race in pid generation that causes pids to be reused immediately
*
* From the mainline commit 5fdee8c4a5e1800489ce61963208f8cc55e42ea1:
*
@@ -9,6 +17,7 @@
* implementation. Furthermore, many shell scripts assume that pid
* numbers will not be used for some length of time.
*
+ * ---------------------------------------------------------------------
* Race Description:
*
* A B
@@ -23,27 +32,7 @@
* // Next fork()...
* last = pid_ns->last_pid; // == n
* pid = last + 1;
- *
- * Copyright (C) 2010 Red Hat, Inc.
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU General Public
- * License as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- *
- * Further, this software is distributed without any warranty that it
- * is free of the rightful claim of any third person regarding
- * infringement or the like. Any license provided herein, whether
- * implied or otherwise, applies only to this software file. Patent
- * licenses, if any, provided herein do not apply to combinations of
- * this program with other software, or any other product whatsoever.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA.
+ * ---------------------------------------------------------------------
*/
#include <sys/types.h>
@@ -54,101 +43,82 @@
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
-#include "test.h"
-
-char *TCID = "fork13";
-int TST_TOTAL = 1;
-static unsigned long pid_max;
+#include "tst_test.h"
-#define PID_MAX_PATH "/proc/sys/kernel/pid_max"
#define PID_MAX 32768
+#define PID_MAX_STR "32768"
#define RETURN 256
+#define MAX_ITERATIONS 1000000
-static void setup(void);
-static int pid_distance(pid_t first, pid_t second);
-static void cleanup(void);
-static void check(void);
-
-int main(int argc, char *argv[])
+/* The distance mod PIDMAX between two pids, where the first pid is
+ expected to be smaller than the second. */
+static int pid_distance(pid_t first, pid_t second)
{
- tst_parse_opts(argc, argv, NULL, NULL);
- setup();
- check();
- cleanup();
- tst_exit();
+ return (second + PID_MAX - first) % PID_MAX;
}
static void check(void)
{
- long lc;
- pid_t last_pid = 0;
+ pid_t prev_pid = 0;
pid_t pid;
- int child_exit_code, distance, reaped, status;
-
- for (lc = 0; TEST_LOOPING(lc); lc++) {
- tst_count = 0;
- child_exit_code = lc % RETURN;
- switch (pid = fork()) {
- case -1:
- tst_brkm(TBROK | TERRNO, cleanup, "fork");
- case 0:
- exit(child_exit_code);
- default:
- if (lc > 0) {
- distance = pid_distance(last_pid, pid);
- if (distance == 0) {
- tst_resm(TFAIL,
- "Unexpected pid sequence: "
- "previous fork: pid=%d, "
- "current fork: pid=%d for "
- "iteration=%ld.", last_pid,
- pid, lc);
- return;
- }
- }
- last_pid = pid;
-
- reaped = waitpid(pid, &status, 0);
- if (reaped != pid) {
- tst_resm(TFAIL,
- "Wait return value: expected pid=%d, "
- "got %d, iteration %ld.", pid, reaped,
- lc);
- return;
- } else if (WEXITSTATUS(status) != child_exit_code) {
- tst_resm(TFAIL, "Unexpected exit status %x, "
- "iteration %ld.", WEXITSTATUS(status),
- lc);
+ int i, distance, reaped, status, retval;
+
+ for (i = 0; i < MAX_ITERATIONS; i++) {
+ retval = i % RETURN;
+
+ pid = SAFE_FORK();
+ if (!pid)
+ exit(retval);
+
+ if (prev_pid) {
+ distance = pid_distance(prev_pid, pid);
+ if (distance == 0) {
+ tst_res(TFAIL,
+ "Unexpected pid sequence: prev_pid=%i, pid=%i for iteration=%i",
+ prev_pid, pid, i);
return;
}
}
- }
- tst_resm(TPASS, "%ld pids forked, all passed", lc);
-}
-static void setup(void)
-{
- tst_require_root();
+ prev_pid = pid;
- tst_sig(FORK, DEF_HANDLER, cleanup);
- TEST_PAUSE;
+ reaped = SAFE_WAITPID(pid, &status, 0);
- /* Backup pid_max value. */
- SAFE_FILE_SCANF(NULL, PID_MAX_PATH, "%lu", &pid_max);
+ if (reaped != pid) {
+ tst_res(TFAIL,
+ "Wrong pid %i returned from waitpid() expected %i",
+ reaped, pid);
+ return;
+ }
- SAFE_FILE_PRINTF(NULL, PID_MAX_PATH, "%d", PID_MAX);
-}
+ if (WEXITSTATUS(status) != retval) {
+ tst_res(TFAIL,
+ "Wrong process exit value %i expected %i",
+ WEXITSTATUS(status), retval);
+ return;
+ }
-static void cleanup(void)
-{
- /* Restore pid_max value. */
- FILE_PRINTF(PID_MAX_PATH, "%lu", pid_max);
-}
+ if (!tst_remaining_runtime()) {
+ tst_res(TINFO, "Runtime exhausted, exiting...");
+ break;
+ }
+ }
-/* The distance mod PIDMAX between two pids, where the first pid is
- expected to be smaller than the second. */
-static int pid_distance(pid_t first, pid_t second)
-{
- return (second + PID_MAX - first) % PID_MAX;
+ tst_res(TPASS, "%i pids forked, all passed", i);
}
+
+static struct tst_test test = {
+ .needs_root = 1,
+ .forks_child = 1,
+ .max_runtime = 600,
+ .test_all = check,
+ .save_restore = (const struct tst_path_val[]) {
+ {"!/proc/sys/kernel/pid_max", PID_MAX_STR},
+ {}
+ },
+ .tags = (const struct tst_tag[]) {
+ {"linux-git", "5fdee8c4a5e1"},
+ {}
+ }
+};
--
2.35.1
More information about the ltp
mailing list