[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