[LTP] [PATCH] waitpid03: Convert to new API
Martin Doucha
mdoucha@suse.cz
Mon Jan 29 16:48:05 CET 2024
Simplify the test by having the child processes immediately exit()
instead of killing them with a signal. Also check the return value
more thoroughly, including that waiting for invalid PID will cause
ECHILD error.
Signed-off-by: Martin Doucha <mdoucha@suse.cz>
---
testcases/kernel/syscalls/waitpid/waitpid03.c | 224 +++++-------------
1 file changed, 55 insertions(+), 169 deletions(-)
diff --git a/testcases/kernel/syscalls/waitpid/waitpid03.c b/testcases/kernel/syscalls/waitpid/waitpid03.c
index 7eae3ad5a..573b30559 100644
--- a/testcases/kernel/syscalls/waitpid/waitpid03.c
+++ b/testcases/kernel/syscalls/waitpid/waitpid03.c
@@ -1,194 +1,80 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
/*
- *
- * Copyright (c) International Business Machines Corp., 2001
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
- * the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ * Copyright (c) International Business Machines Corp., 2001
+ * Copyright (c) 2024 SUSE LLC <mdoucha@suse.cz>
*/
-/*
- * NAME
- * waitpid03.c
- *
- * DESCRIPTION
- * Check that parent waits unitl specific child has returned.
- *
- * ALGORITHM
- * Parent forks numerous (22 = MAXUPRC - 3) children, and starts waits :
- * Should only wait for the specific child, a second wait on the same
- * child should return with -1 and not one of the other zombied
- * children.
+/*\
+ * [Description]
*
- * USAGE: <for command-line>
- * waitpid03 [-c n] [-i n] [-I x] [-P x] [-t]
- * where, -c n : Run n copies concurrently.
- * -i n : Execute test n times.
- * -I x : Execute test for x seconds.
- * -P x : Pause for x seconds between iterations.
- * -t : Turn on syscall timing.
- *
- * History
- * 07/2001 John George
- * -Ported
- * 04/2002 wjhuie sigset cleanups
- *
- * Restrictions
- * None
+ * Check that waitpid() returns the exit status of a specific child process
+ * and repeated call on the same process will fail with ECHILD
*/
-#define DEBUG 0
-
+#include <stdlib.h>
#include <sys/types.h>
#include <signal.h>
#include <errno.h>
#include <sys/wait.h>
-#include "test.h"
-static void do_child(int);
-static void setup(void);
-static void cleanup(void);
+#include "tst_test.h"
-char *TCID = "waitpid03";
-int TST_TOTAL = 1;
+#define MAX_CHILDREN 25
-#define MAXUPRC 25
+static pid_t children[MAX_CHILDREN];
-static int ikids;
-static int pid[MAXUPRC];
-static int condition_number;
+void check_waitpid(pid_t pid, int reaped)
+{
+ TEST(waitpid(pid, NULL, 0));
-#ifdef UCLINUX
-static void do_child_uclinux(void);
-static int ikids_uclinux;
-#endif
+ if (!reaped && pid == (pid_t)TST_RET) {
+ tst_res(TPASS, "waitpid(%d) returned correct PID", pid);
+ return;
+ }
-int main(int argc, char **argv)
-{
- int lc;
-
- int status, ret;
-
- tst_parse_opts(argc, argv, NULL, NULL);
-#ifdef UCLINUX
- maybe_run_child(&do_child, "d", &ikids_uclinux);
-#endif
-
- setup();
-
- /* check for looping state if -i option is given */
- for (lc = 0; TEST_LOOPING(lc); lc++) {
- /* reset tst_count in case we are looping */
- tst_count = 0;
-
- /*
- * Set SIGTERM to SIG_DFL as test driver sets up to ignore
- * SIGTERM
- */
- if ((sig_t) signal(SIGTERM, SIG_DFL) == SIG_ERR) {
- tst_resm(TFAIL, "Signal SIGTERM failed, errno = %d",
- errno);
-
- }
-
- while (++ikids < MAXUPRC) {
- pid[ikids] = FORK_OR_VFORK();
- if (pid[ikids] > 0) {
- if (DEBUG)
- tst_resm(TINFO, "child # %d", ikids);
- } else if (pid[ikids] == -1) {
- tst_brkm(TBROK|TERRNO, cleanup, "cannot open "
- "fork #%d", ikids);
-
- } else {
-#ifdef UCLINUX
- if (self_exec(argv[0], "d", ikids) < 0) {
- tst_resm(TFAIL, "cannot self_exec #%d",
- ikids);
- }
-#else
- do_child(ikids);
-#endif
- }
- }
-
- for (ikids = 1; ikids < MAXUPRC; ikids++) {
- if (DEBUG)
- tst_resm(TINFO, "Killing #%d", ikids);
- kill(pid[ikids], SIGTERM);
- }
-
- ikids = 0;
- condition_number = 1;
-
- /* Wait on one specific child */
- if (DEBUG)
- tst_resm(TINFO, "Waiting for child:#%d", MAXUPRC / 2);
- ret = waitpid(pid[MAXUPRC / 2], &status, 0);
- if (ret != pid[MAXUPRC / 2]) {
- tst_resm(TFAIL, "condition %d test failed. "
- "waitpid(%d) returned %d.",
- condition_number, pid[MAXUPRC / 2], ret);
- } else {
- tst_resm(TPASS, "Got correct child PID");
- }
- condition_number++;
-
- /*
- * Child has already been waited on, waitpid should return
- * -1
- */
- ret = waitpid(pid[MAXUPRC / 2], &status, 0);
- if (ret != -1) {
- tst_resm(TFAIL, "condition %d test failed",
- condition_number);
- } else {
- tst_resm(TPASS, "Condition %d test passed",
- condition_number);
- }
- condition_number++;
+ if (reaped && TST_RET == -1 && TST_ERR == ECHILD) {
+ tst_res(TPASS | TTERRNO, "waitpid(%d) failed on reaped child",
+ pid);
+ return;
}
- cleanup();
- tst_exit();
-}
+ if (TST_RET == -1) {
+ tst_res(TFAIL | TTERRNO, "waitpid(%d) failed", pid);
+ return;
+ }
-static void do_child(int ikids)
-{
- if (DEBUG)
- tst_resm(TINFO, "child:%d", ikids);
- pause();
- exit(0);
-}
+ if (TST_RET < 0) {
+ tst_res(TFAIL | TTERRNO,
+ "Unexpected waitpid(%d) return value %ld", pid,
+ TST_RET);
+ return;
+ }
-#ifdef UCLINUX
-/*
- * do_child_uclinux()
- * run do_child with the appropriate ikids variable
- */
-static void do_child_uclinux(void)
-{
- do_child(ikids_uclinux);
+ tst_res(TFAIL, "waitpid(%d) returned unexpected PID %ld", pid, TST_RET);
}
-#endif
-static void setup(void)
+void run(void)
{
- TEST_PAUSE;
-}
+ int i;
-static void cleanup(void)
-{
- while (ikids-- > 1)
- kill(pid[ikids], SIGKILL);
+ for (i = 0; i < MAX_CHILDREN; i++) {
+ children[i] = SAFE_FORK();
+
+ /* Children have nothing to do... */
+ if (!children[i])
+ exit(0);
+ }
+
+ /* Wait for one specific child */
+ i = MAX_CHILDREN / 2;
+ check_waitpid(children[i], 0);
+
+ /* Try the same child again after it was reaped */
+ check_waitpid(children[i], 1);
+ tst_reap_children();
}
+
+static struct tst_test test = {
+ .test_all = run,
+ .forks_child = 1
+};
--
2.42.1
More information about the ltp
mailing list