All of lore.kernel.org
 help / color / mirror / Atom feed
* [LTP] [PATCH V3 1/6] tst_safe_macros: SAFE_GETPGID
@ 2016-08-04 14:16 Stanislav Kholmanskikh
  2016-08-04 14:16 ` [LTP] [PATCH V3 2/6] tst_test: make reap_children() part of the test API Stanislav Kholmanskikh
  0 siblings, 1 reply; 9+ messages in thread
From: Stanislav Kholmanskikh @ 2016-08-04 14:16 UTC (permalink / raw)
  To: ltp

Signed-off-by: Stanislav Kholmanskikh <stanislav.kholmanskikh@oracle.com>
---
No changes since V1


 include/tst_safe_macros.h |   16 ++++++++++++++++
 1 files changed, 16 insertions(+), 0 deletions(-)

diff --git a/include/tst_safe_macros.h b/include/tst_safe_macros.h
index 540fcb2..3cf154e 100644
--- a/include/tst_safe_macros.h
+++ b/include/tst_safe_macros.h
@@ -135,6 +135,22 @@ static inline int safe_setpgid(const char *file, const int lineno,
 #define SAFE_SETPGID(pid, pgid) \
 	safe_setpgid(__FILE__, __LINE__, (pid), (pgid));
 
+static inline pid_t safe_getpgid(const char *file, const int lineno,
+				 pid_t pid)
+{
+	pid_t pgid;
+
+	pgid = getpgid(pid);
+	if (pgid == -1) {
+		tst_brk_(file, lineno, TBROK | TERRNO,
+			 "getpgid(%i) failed", pid);
+	}
+
+	return pgid;
+}
+#define SAFE_GETPGID(pid) \
+	safe_getpgid(__FILE__, __LINE__, (pid))
+
 #define SAFE_UNLINK(pathname) \
 	safe_unlink(__FILE__, __LINE__, NULL, (pathname))
 
-- 
1.7.1


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [LTP] [PATCH V3 2/6] tst_test: make reap_children() part of the test API
  2016-08-04 14:16 [LTP] [PATCH V3 1/6] tst_safe_macros: SAFE_GETPGID Stanislav Kholmanskikh
@ 2016-08-04 14:16 ` Stanislav Kholmanskikh
  2016-08-04 14:16   ` [LTP] [PATCH V3 3/6] waitpid06: use the new API Stanislav Kholmanskikh
  2016-08-04 16:13   ` [LTP] [PATCH V3 2/6] tst_test: make reap_children() part of the test API Cyril Hrubis
  0 siblings, 2 replies; 9+ messages in thread
From: Stanislav Kholmanskikh @ 2016-08-04 14:16 UTC (permalink / raw)
  To: ltp

Signed-off-by: Stanislav Kholmanskikh <stanislav.kholmanskikh@oracle.com>
---
This is a new patch in this series.

doc/test-writing-guidelines.txt |   12 ++++++++++++
 include/tst_test.h              |    6 ++++++
 lib/tst_test.c                  |    6 +++---
 3 files changed, 21 insertions(+), 3 deletions(-)

diff --git a/doc/test-writing-guidelines.txt b/doc/test-writing-guidelines.txt
index 68b4602..6ae27b6 100644
--- a/doc/test-writing-guidelines.txt
+++ b/doc/test-writing-guidelines.txt
@@ -653,6 +653,18 @@ exit uncleanly all you need to do is to wait for such children from the
 'test()' function so that it's reaped before the main test exits the 'test()'
 function.
 
+[source,c]
+-------------------------------------------------------------------------------
+#include "tst_test.h"
+
+void tst_reap_children(void);
+-------------------------------------------------------------------------------
+
+The 'tst_reap_children()' function makes the process wait for all of its
+children and exits with 'tst_brk(TBROK, ...)' if any of them returned
+a non zero exit code. This function may be called only from the main
+test process.
+
 2.2.9 Fork() and Parent-child synchronization
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
diff --git a/include/tst_test.h b/include/tst_test.h
index b02168a..7e4997f 100644
--- a/include/tst_test.h
+++ b/include/tst_test.h
@@ -64,6 +64,12 @@ pid_t safe_fork(const char *filename, unsigned int lineno);
 #include "tst_safe_net.h"
 #include "tst_safe_pthread.h"
 
+/*
+ * Wait for all children and exit with TBROK if
+ * any of them returned a non-zero exit status.
+ */
+void tst_reap_children(void);
+
 struct tst_option {
 	char *optstr;
 	char **arg;
diff --git a/lib/tst_test.c b/lib/tst_test.c
index 6c93152..6f635ec 100644
--- a/lib/tst_test.c
+++ b/lib/tst_test.c
@@ -287,7 +287,7 @@ static void check_child_status(pid_t pid, int status)
 	}
 }
 
-static void reap_children(void)
+void tst_reap_children(void)
 {
 	int status;
 	pid_t pid;
@@ -644,7 +644,7 @@ static void run_tests(void)
 			exit(0);
 		}
 
-		reap_children();
+		tst_reap_children();
 
 		if (results_equal(&saved_results, results))
 			tst_brk(TBROK, "Test haven't reported results!");
@@ -659,7 +659,7 @@ static void run_tests(void)
 			exit(0);
 		}
 
-		reap_children();
+		tst_reap_children();
 
 		if (results_equal(&saved_results, results))
 			tst_brk(TBROK, "Test %i haven't reported results!", i);
-- 
1.7.1


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [LTP] [PATCH V3 3/6] waitpid06: use the new API
  2016-08-04 14:16 ` [LTP] [PATCH V3 2/6] tst_test: make reap_children() part of the test API Stanislav Kholmanskikh
@ 2016-08-04 14:16   ` Stanislav Kholmanskikh
  2016-08-04 14:16     ` [LTP] [PATCH V3 4/6] waitpid07: " Stanislav Kholmanskikh
  2016-08-04 16:13   ` [LTP] [PATCH V3 2/6] tst_test: make reap_children() part of the test API Cyril Hrubis
  1 sibling, 1 reply; 9+ messages in thread
From: Stanislav Kholmanskikh @ 2016-08-04 14:16 UTC (permalink / raw)
  To: ltp

 * Use the new LTP API
 * Use the checkpoint interface instead of wait_for_parent()
 * Drop UCLINUX support

Common items were moved to a header file.

Signed-off-by: Stanislav Kholmanskikh <stanislav.kholmanskikh@oracle.com>
---
Changes since V2:
 * Use tst_reap_children() in waitpid_test()
 * Removed reduntant tst_res(TFAIL) next to reap_children()

 Changes since V1:
 * Rename cleanup() to waitpid_cleanup()
 * Kill child_1 pid in waitpid_cleanup()
 * Remove waitpid() calls from waitpid_cleanup()
 * Move mmap/unmap of fork_kid_pid to the setup
   and cleanup functions
 * Removed the 'fail = FAILED' logic
 * Created reap_children(). It calls waitpid() with necessary
   arguments and verifies that all the expected pids have
   terminated as they should

testcases/kernel/syscalls/waitpid/waitpid06.c      |  313 +++-----------------
 testcases/kernel/syscalls/waitpid/waitpid_common.h |  136 +++++++++
 2 files changed, 173 insertions(+), 276 deletions(-)
 create mode 100644 testcases/kernel/syscalls/waitpid/waitpid_common.h

diff --git a/testcases/kernel/syscalls/waitpid/waitpid06.c b/testcases/kernel/syscalls/waitpid/waitpid06.c
index dbbc104..66d5ebc 100644
--- a/testcases/kernel/syscalls/waitpid/waitpid06.c
+++ b/testcases/kernel/syscalls/waitpid/waitpid06.c
@@ -1,303 +1,64 @@
 /*
+ * Copyright (c) International Business Machines  Corp., 2001
  *
- *   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 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.
  *
- *   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.
  *
- *   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
+ * History
+ *	07/2001 John George
+ *		-Ported
+ *      04/2002 wjhuie sigset cleanups
  */
 
 /*
- * NAME
- *	waitpid06.c
- *
  * DESCRIPTION
- *	Tests to see if pid's returned from fork and waitpid are same.
+ *	Tests to see if pids returned from fork and waitpid are same.
  *
  * ALGORITHM
  *	Check proper functioning of waitpid with pid = -1 and arg = 0
- *
- * USAGE:  <for command-line>
- *      waitpid06 [-c n] [-e] [-i n] [-I x] [-P x] [-t]
- *      where,  -c n : Run n copies concurrently.
- *              -e   : Turn on errno logging.
- *              -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
  */
 
-#include <sys/types.h>
-#include <signal.h>
-#include <errno.h>
-#include <sys/wait.h>
-#include "test.h"
-
-static void setup_sigint(void);
-static void do_child_1(void);
-static void setup(void);
-static void cleanup(void);
-
-char *TCID = "waitpid06";
-int TST_TOTAL = 1;
-volatile int intintr;
-static void inthandlr();
-static void do_exit(void);
-static int flag;
-
-#define	FAILED	1
-#define	MAXKIDS	8
-
-#ifdef UCLINUX
-static char *argv0;
-static void do_child_2_uclinux(void);
-#endif
-
-int main(int argc, char **argv)
-{
-	int lc;
-	int fail = 0;
-	int pid;
-	int status;
-
-	tst_parse_opts(argc, argv, NULL, NULL);
-
-#ifdef UCLINUX
-	argv0 = argv[0];
-
-	maybe_run_child(&do_child_1, "n", 1);
-	maybe_run_child(&do_child_2_uclinux, "n", 2);
-#endif
-
-	setup();
-
-	for (lc = 0; TEST_LOOPING(lc); lc++) {
-		/* reset tst_count in case we are looping */
-		tst_count = 0;
-
-		pid = FORK_OR_VFORK();
-		if (pid < 0) {
-			tst_resm(TINFO, "Fork Failed, may be OK under stress");
-			exit(pid);
-		} else if (pid == 0) {
-			/*
-			 * Child:
-			 * Set up to catch SIGINT.  The kids will wait till a
-			 * SIGINT has been received before they proceed.
-			 */
-#ifdef UCLINUX
-			if (self_exec(argv[0], "n", 1) < 0) {
-				tst_resm(TINFO, "self_exec failed");
-				exit(pid);
-			}
-#else
-			do_child_1();
-#endif
-		} else {	/* parent */
-			fail = 0;
-			waitpid(pid, &status, 0);
-			if (WEXITSTATUS(status) != 0) {
-				tst_resm(TFAIL, "child returned bad status");
-				fail = 1;
-			}
-			if (fail)
-				tst_resm(TFAIL, "%s FAILED", TCID);
-			else
-				tst_resm(TPASS, "%s PASSED", TCID);
-		}
-	}
-
-	cleanup();
-	tst_exit();
-}
-
-/*
- * setup_sigint()
- *	Sets up a SIGINT handler
- */
-static void setup_sigint(void)
-{
-	if ((sig_t) signal(SIGINT, inthandlr) == SIG_ERR) {
-		tst_resm(TFAIL, "signal SIGINT failed. " "errno = %d", errno);
-		exit(-1);
-	}
-}
+#include "waitpid_common.h"
 
 static void do_child_1(void)
 {
-	int kid_count, fork_kid_pid[MAXKIDS];
-	int ret_val;
-	int i, j, k, found;
-	int group1, group2;
-	int wait_kid_pid[MAXKIDS], status;
-
-	setup_sigint();
-
-	group1 = getpgrp();
-	for (kid_count = 0; kid_count < MAXKIDS; kid_count++) {
-		if (kid_count == (MAXKIDS / 2))
-			group2 = setpgrp();
-
-		intintr = 0;
-		ret_val = FORK_OR_VFORK();
-		if (ret_val == 0) {	/* child */
-#ifdef UCLINUX
-			if (self_exec(argv0, "n", 2) < 0) {
-				tst_resm(TFAIL, "Fork kid %d failed. "
-					 "errno = %d", kid_count, errno);
-				exit(ret_val);
-			}
-#else
-			do_exit();
-#endif
-		} else if (ret_val < 0) {
-			tst_resm(TFAIL, "Fork kid %d failed. "
-				 "errno = %d", kid_count, errno);
-			exit(ret_val);
-		}
-
-		/* parent */
-		fork_kid_pid[kid_count] = ret_val;
-	}
-
-#ifdef UCLINUX
-	/* Give the kids a chance to setup SIGINT again, since this is
-	 * cleared by exec().
-	 */
-	sleep(3);
-#endif
+	pid_t pid;
+	int i;
 
-	/* Now send all the kids a SIGINT to tell them to
-	 * proceed
-	 */
 	for (i = 0; i < MAXKIDS; i++) {
-		if (kill(fork_kid_pid[i], SIGINT) < 0) {
-			tst_resm(TFAIL, "Kill of child %d "
-				 "failed, errno = %d", i, errno);
-			exit(-1);
-		}
-	}
-
-	/*
-	 * Wait till all kids have terminated.  Stash away their
-	 * pid's in an array.
-	 */
-	kid_count = 0;
-	errno = 0;
-	while (((ret_val = waitpid(-1, &status, 0)) != -1) || (errno == EINTR)) {
-		if (ret_val == -1)
-			continue;
-
-		if (!WIFEXITED(status)) {
-			tst_resm(TFAIL, "Child %d did not exit "
-				 "normally", ret_val);
-			flag = FAILED;
-			printf("status: %d\n", status);
-		} else {
-			if (WEXITSTATUS(status) != 3) {
-				tst_resm(TFAIL, "Child %d"
-					 "exited with wrong "
-					 "status", ret_val);
-				tst_resm(TFAIL, "Expected 3 "
-					 "got %d ", WEXITSTATUS(status));
-				flag = FAILED;
-			}
-		}
-		wait_kid_pid[kid_count++] = ret_val;
-	}
+		if (i == (MAXKIDS / 2))
+			SAFE_SETPGID(0, 0);
 
-	/*
-	 * Check that for every entry in the fork_kid_pid array,
-	 * there is a matching pid in the wait_kid_pid array. If
-	 * not, it's an error.
-	 */
-	for (i = 0; i < kid_count; i++) {
-		found = 0;
-		for (j = 0; j < MAXKIDS; j++) {
-			if (fork_kid_pid[j] == wait_kid_pid[i]) {
-				found = 1;
-				break;
-			}
-		}
+		pid = SAFE_FORK();
+		if (pid == 0)
+			do_exit(0);
 
-		if (!found) {
-			tst_resm(TFAIL, "Did not find a "
-				 "wait_kid_pid for the "
-				 "fork_kid_pid of %d", wait_kid_pid[i]);
-			for (k = 0; k < MAXKIDS; k++) {
-				tst_resm(TFAIL,
-					 "fork_kid_pid[%d] = "
-					 "%d", k, fork_kid_pid[k]);
-			}
-			for (k = 0; k < kid_count; k++) {
-				tst_resm(TFAIL,
-					 "wait_kid_pid[%d] = "
-					 "%d", k, wait_kid_pid[k]);
-			}
-			flag = FAILED;
-		}
+		fork_kid_pid[i] = pid;
 	}
 
-	if (flag)
-		exit(1);
-	else
-		exit(0);
-}
-
-#ifdef UCLINUX
-/*
- * do_child_2_uclinux()
- *	sets up sigint handler again, then calls the normal child 2 function
- */
-static void do_child_2_uclinux(void)
-{
-	setup_sigint();
-	do_exit();
-}
-#endif
-
-static void setup(void)
-{
-	TEST_PAUSE;
-}
+	TST_CHECKPOINT_WAKE2(0, MAXKIDS);
 
-static void cleanup(void)
-{
-}
+	if (reap_children(-1, 0, fork_kid_pid, MAXKIDS))
+		return;
 
-static void inthandlr(void)
-{
-	intintr++;
+	tst_res(TPASS, "Test PASSED");
 }
 
-static void wait_for_parent(void)
-{
-	int testvar;
-
-	while (!intintr)
-		testvar = 0;
-}
-
-static void do_exit(void)
-{
-	wait_for_parent();
-	exit(3);
-}
+static struct tst_test test = {
+	.tid = "waitpid06",
+	.forks_child = 1,
+	.needs_checkpoints = 1,
+	.setup = waitpid_setup,
+	.cleanup = waitpid_cleanup,
+	.test_all = waitpid_test,
+};
diff --git a/testcases/kernel/syscalls/waitpid/waitpid_common.h b/testcases/kernel/syscalls/waitpid/waitpid_common.h
new file mode 100644
index 0000000..008577a
--- /dev/null
+++ b/testcases/kernel/syscalls/waitpid/waitpid_common.h
@@ -0,0 +1,136 @@
+/*
+ * Copyright (c) 2016 Linux Test Project
+ *
+ * Licensed under the GNU GPLv2 or later.
+ * 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.
+ */
+
+#ifndef WAITPID_COMMON_H__
+#define WAITPID_COMMON_H__
+
+#include <sys/types.h>
+#include <errno.h>
+#include <sys/wait.h>
+#include <stdlib.h>
+#include "tst_test.h"
+
+#define	MAXKIDS	8
+
+static pid_t *fork_kid_pid;
+static pid_t child_1_pid;
+
+static void do_child_1(void);
+
+static void waitpid_setup(void)
+{
+	fork_kid_pid = SAFE_MMAP(NULL, sizeof(*fork_kid_pid) * MAXKIDS,
+				 PROT_READ | PROT_WRITE,
+				 MAP_SHARED | MAP_ANONYMOUS, -1, 0);
+}
+
+static void waitpid_cleanup(void)
+{
+	int i;
+
+	for (i = 0; i < MAXKIDS; i++) {
+		if (fork_kid_pid[i] > 0)
+			kill(fork_kid_pid[i], SIGKILL);
+	}
+
+	if (child_1_pid > 0)
+		kill(child_1_pid, SIGKILL);
+
+	munmap(fork_kid_pid, sizeof(*fork_kid_pid) * MAXKIDS);
+}
+
+static void waitpid_test(void)
+{
+	child_1_pid = SAFE_FORK();
+	if (child_1_pid == 0) {
+		do_child_1();
+	} else {
+		tst_reap_children();
+		child_1_pid = 0;
+	}
+}
+
+static void do_exit(int stop)
+{
+	TST_CHECKPOINT_WAIT(0);
+
+	if (stop)
+		kill(getpid(), SIGSTOP);
+
+	exit(3);
+}
+
+static int reap_children(pid_t wp_pid, int wp_opts, pid_t *children, int len)
+{
+	pid_t pid;
+	int i;
+	int status;
+
+	for (;;) {
+		pid = waitpid(wp_pid, &status, wp_opts);
+
+		if (pid == -1) {
+			if (errno == EINTR)
+				continue;
+
+			break;
+		}
+
+		if (pid == 0) {
+			if (wp_opts & WNOHANG)
+				continue;
+
+			tst_res(TFAIL, "waitpid() returned 0 unexpectedly");
+			return -1;
+		}
+
+		for (i = 0; i < len; i++) {
+			if (pid == children[i]) {
+				children[i] = 0;
+				break;
+			}
+		}
+
+		if (i == len) {
+			tst_res(TFAIL, "Pid %d not found", pid);
+			return -1;
+		}
+
+		if (!WIFEXITED(status)) {
+			tst_res(TFAIL, "Pid %d exited abnormally", pid);
+			return -1;
+		}
+
+		if (WEXITSTATUS(status) != 3) {
+			tst_res(TFAIL, "Pid %d exited with %d, expected 3",
+				pid, WEXITSTATUS(status));
+			return -1;
+		}
+	}
+
+	for (i = 0; i < len; i++) {
+		if (children[i]) {
+			tst_res(TFAIL, "Pid %d not reaped", children[i]);
+			return -1;
+		}
+	}
+
+	return 0;
+}
+
+#endif /* WAITPID_COMMON_H__ */
-- 
1.7.1


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [LTP] [PATCH V3 4/6] waitpid07: use the new API
  2016-08-04 14:16   ` [LTP] [PATCH V3 3/6] waitpid06: use the new API Stanislav Kholmanskikh
@ 2016-08-04 14:16     ` Stanislav Kholmanskikh
  2016-08-04 14:16       ` [LTP] [PATCH V3 5/6] waitpid08: " Stanislav Kholmanskikh
  0 siblings, 1 reply; 9+ messages in thread
From: Stanislav Kholmanskikh @ 2016-08-04 14:16 UTC (permalink / raw)
  To: ltp

Signed-off-by: Stanislav Kholmanskikh <stanislav.kholmanskikh@oracle.com>
---
Changes since V2:
 * Removed reduntant tst_res(TFAIL) next to reap_children()

Changes since V1:
 * Use waitpid_setup(), waitpid_cleanup()
 * Use reap_children()

 testcases/kernel/syscalls/waitpid/waitpid07.c |  329 ++++---------------------
 1 files changed, 44 insertions(+), 285 deletions(-)

diff --git a/testcases/kernel/syscalls/waitpid/waitpid07.c b/testcases/kernel/syscalls/waitpid/waitpid07.c
index 92f921d..74da914 100644
--- a/testcases/kernel/syscalls/waitpid/waitpid07.c
+++ b/testcases/kernel/syscalls/waitpid/waitpid07.c
@@ -1,314 +1,73 @@
 /*
+ * Copyright (c) International Business Machines  Corp., 2001
  *
- *   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 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.
  *
- *   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.
  *
- *   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
+ * History
+ *	07/2001 John George
+ *		-Ported
+ *      04/2002 wjhuie sigset cleanups
  */
 
 /*
- * NAME
- *	waitpid07.c
- *
  * DESCRIPTION
- *	Tests to see if pid's returned from fork and waitpid are same.
+ *	Tests to see if pids returned from fork and waitpid are same.
  *
  * ALGORITHM
  *	Check proper functioning of waitpid with pid = -1 and arg = WNOHANG
- *
- * USAGE:  <for command-line>
- *      waitpid07 [-c n] [-e] [-i n] [-I x] [-P x] [-t]
- *      where,  -c n : Run n copies concurrently.
- *              -e   : Turn on errno logging.
- *              -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
  */
 
-#include <sys/types.h>
-#include <signal.h>
-#include <errno.h>
-#include <sys/wait.h>
-#include "test.h"
-
-static void setup_sigint(void);
-static void do_child_1(void);
-static void setup(void);
-static void cleanup(void);
-
-char *TCID = "waitpid07";
-int TST_TOTAL = 1;
-
-volatile int intintr;
-static int flag;
-static void inthandlr();
-static void do_exit(void);
-
-#define	FAILED	1
-#define MAXKIDS	8
-
-#ifdef UCLINUX
-static char *argv0;
-static void do_child_2_uclinux(void);
-#endif
-
-int main(int argc, char **argv)
-{
-	int lc;
-
-	int status;
-	int fail = 0;
-	int pid;
-
-	tst_parse_opts(argc, argv, NULL, NULL);
-
-#ifdef UCLINUX
-	argv0 = argv[0];
-
-	maybe_run_child(&do_child_1, "n", 1);
-	maybe_run_child(&do_child_2_uclinux, "n", 2);
-#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;
-
-		pid = FORK_OR_VFORK();
-		if (pid < 0) {
-			tst_resm(TFAIL, "Fork Failed, may be OK under stress");
-		} else if (pid == 0) {
-
-			/*
-			 * Child:
-			 * Set up to catch SIGINT.  The kids will wait till a
-			 * SIGINT has been received before they proceed.
-			 */
-#ifdef UCLINUX
-			if (self_exec(argv[0], "n", 1) < 0) {
-				tst_resm(TINFO, "self_exec failed");
-				exit(pid);
-			}
-#else
-			do_child_1();
-#endif
-		} else {
-			fail = 0;
-			waitpid(pid, &status, 0);
-			if (WEXITSTATUS(status) != 0) {
-				tst_resm(TFAIL, "child returned bad status");
-				fail = 1;
-			}
-			if (fail)
-				tst_resm(TFAIL, "%s FAILED", TCID);
-			else
-				tst_resm(TPASS, "%s PASSED", TCID);
-		}
-	}
-
-	cleanup();
-	tst_exit();
-}
-
-/*
- * setup_sigint()
- *	Sets up a SIGINT handler
- */
-static void setup_sigint(void)
-{
-	if ((sig_t) signal(SIGINT, inthandlr) == SIG_ERR) {
-		tst_resm(TFAIL, "signal SIGINT failed. " "errno = %d", errno);
-		exit(-1);
-	}
-}
+#include "waitpid_common.h"
 
 static void do_child_1(void)
 {
-	int kid_count, fork_kid_pid[MAXKIDS];
-	int ret_val;
-	int i, j, k, found;
-	int group1, group2;
-	int wait_kid_pid[MAXKIDS], status;
-
-	setup_sigint();
-
-	group1 = getpgrp();
-
-	for (kid_count = 0; kid_count < MAXKIDS; kid_count++) {
-		if (kid_count == (MAXKIDS / 2))
-			group2 = setpgrp();
-
-		intintr = 0;
-		ret_val = FORK_OR_VFORK();
-		if (ret_val == 0) {
-#ifdef UCLINUX
-			if (self_exec(argv0, "n", 2) < 0) {
-				tst_resm(TFAIL, "Fork kid %d failed. "
-					 "errno = %d", kid_count, errno);
-				exit(ret_val);
-			}
-#else
-			do_exit();
-#endif
-		}
-
-		if (ret_val < 0) {
-			tst_brkm(TFAIL, NULL, "Fork kid %d failed. "
-				 "errno = %d", kid_count, errno);
-		}
-
-		/* parent */
-		fork_kid_pid[kid_count] = ret_val;
-	}
-
-	/* Check that waitpid with WNOHANG returns zero */
-	ret_val = waitpid(-1, &status, WNOHANG);
-	if (ret_val != 0) {
-		tst_resm(TFAIL, "Waitpid returned wrong value");
-		tst_resm(TFAIL, "Expected 0 got %d", ret_val);
-		flag = FAILED;
-	}
-#ifdef UCLINUX
-	/* Give the kids a chance to setup SIGINT again, since this is
-	 * cleared by exec().
-	 */
-	sleep(3);
-#endif
+	pid_t pid;
+	int i;
+	int status;
 
-	/* Now send all the kids a SIGINT to tell them to
-	 * proceed
-	 */
 	for (i = 0; i < MAXKIDS; i++) {
-		if (kill(fork_kid_pid[i], SIGINT) < 0) {
-			tst_brkm(TFAIL, NULL, "Kill of child %d "
-				 "failed, errno = %d", i, errno);
-		}
-	}
+		if (i == (MAXKIDS / 2))
+			SAFE_SETPGID(0, 0);
 
-	/*
-	 * Wait till all kids have terminated.  Stash away their
-	 * pid's in an array.
-	 */
-	kid_count = 0;
-	errno = 0;
-	while (((ret_val = waitpid(-1, &status, WNOHANG)) != -1)
-	       || (errno == EINTR)) {
-		if ((ret_val == -1) || (ret_val == 0))
-			continue;
+		pid = SAFE_FORK();
+		if (pid == 0)
+			do_exit(0);
 
-		if (!WIFEXITED(status)) {
-			tst_resm(TFAIL, "Child %d did not exit "
-				 "normally", ret_val);
-			flag = FAILED;
-		} else {
-			if (WEXITSTATUS(status) != 3) {
-				tst_resm(TFAIL, "Child %d "
-					 "exited with wrong "
-					 "status", ret_val);
-				tst_resm(TFAIL, "Expected 3 "
-					 "got %d ", WEXITSTATUS(status));
-				flag = FAILED;
-			}
-		}
-		wait_kid_pid[kid_count++] = ret_val;
+		fork_kid_pid[i] = pid;
 	}
 
-	/*
-	 * Check that for every entry in the fork_kid_pid array,
-	 * there is a matching pid in the wait_kid_pid array. If
-	 * not, it's an error.
-	 */
-	for (i = 0; i < kid_count; i++) {
-		found = 0;
-		for (j = 0; j < MAXKIDS; j++) {
-			if (fork_kid_pid[j] == wait_kid_pid[i]) {
-				found = 1;
-				break;
-			}
-		}
-
-		if (!found) {
-			tst_resm(TFAIL, "Did not find a "
-				 "wait_kid_pid for the "
-				 "fork_kid_pid of %d", wait_kid_pid[i]);
-			for (k = 0; k < MAXKIDS; k++) {
-				tst_resm(TFAIL,
-					 "fork_kid_pid[%d] = "
-					 "%d", k, fork_kid_pid[k]);
-			}
-			for (k = 0; k < kid_count; k++) {
-				tst_resm(TFAIL,
-					 "wait_kid_pid[%d] = "
-					 "%d", k, wait_kid_pid[k]);
-			}
-			flag = FAILED;
-		}
+	/* Check that waitpid with WNOHANG returns zero */
+	pid = waitpid(-1, &status, WNOHANG);
+	if (pid != 0) {
+		tst_res(TFAIL, "waitpid() returned %d, expected 0",
+			pid);
+		return;
 	}
 
-	if (flag)
-		exit(1);
-	else
-		exit(0);
-}
-
-#ifdef UCLINUX
-/*
- * do_child_2_uclinux()
- *	sets up sigint handler again, then calls the normal child 2 function
- */
-static void do_child_2_uclinux(void)
-{
-	setup_sigint();
-	do_exit();
-}
-#endif
+	TST_CHECKPOINT_WAKE2(0, MAXKIDS);
 
-static void setup(void)
-{
-	TEST_PAUSE;
-}
+	if (reap_children(-1, WNOHANG, fork_kid_pid, MAXKIDS))
+		return;
 
-static void cleanup(void)
-{
+	tst_res(TPASS, "Test PASSED");
 }
 
-static void inthandlr(void)
-{
-	intintr++;
-}
-
-static void wait_for_parent(void)
-{
-	int testvar;
-
-	while (!intintr)
-		testvar = 0;
-}
-
-static void do_exit(void)
-{
-	wait_for_parent();
-	exit(3);
-}
+static struct tst_test test = {
+	.tid = "waitpid07",
+	.forks_child = 1,
+	.needs_checkpoints = 1,
+	.setup = waitpid_setup,
+	.cleanup = waitpid_cleanup,
+	.test_all = waitpid_test,
+};
-- 
1.7.1


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [LTP] [PATCH V3 5/6] waitpid08: use the new API
  2016-08-04 14:16     ` [LTP] [PATCH V3 4/6] waitpid07: " Stanislav Kholmanskikh
@ 2016-08-04 14:16       ` Stanislav Kholmanskikh
  2016-08-04 14:16         ` [LTP] [PATCH V3 6/6] waitpid11: " Stanislav Kholmanskikh
  0 siblings, 1 reply; 9+ messages in thread
From: Stanislav Kholmanskikh @ 2016-08-04 14:16 UTC (permalink / raw)
  To: ltp

Signed-off-by: Stanislav Kholmanskikh <stanislav.kholmanskikh@oracle.com>
---
Changes since V2:
 * Removed reduntant tst_res(TFAIL) next to reap_children()

Changes since V1:
 * Use waitpid_setup(), waitpid_cleanup()
 * Use reap_children()
 * Use tst_strerrno

 testcases/kernel/syscalls/waitpid/waitpid08.c |  353 ++++---------------------
 1 files changed, 53 insertions(+), 300 deletions(-)

diff --git a/testcases/kernel/syscalls/waitpid/waitpid08.c b/testcases/kernel/syscalls/waitpid/waitpid08.c
index b2e9e9b..0f0ee9d 100644
--- a/testcases/kernel/syscalls/waitpid/waitpid08.c
+++ b/testcases/kernel/syscalls/waitpid/waitpid08.c
@@ -1,341 +1,94 @@
 /*
+ * Copyright (c) International Business Machines  Corp., 2001
  *
- *   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 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.
  *
- *   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.
  *
- *   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
+ * History
+ *	07/2001 John George
+ *		-Ported
+ *      04/2002 wjhuie sigset cleanups
  */
 
 /*
- * NAME
- *	waitpid08.c
- *
  * DESCRIPTION
- *	Tests to see if pid's returned from fork and waitpid are same
+ *	Tests to see if pids returned from fork and waitpid are same.
  *
  * ALGORITHM
  *	Check proper functioning of waitpid with pid = -1 and arg =
  *	WUNTRACED
- *
- * USAGE:  <for command-line>
- *      waitpid08 [-c n] [-e] [-i n] [-I x] [-P x] [-t]
- *      where,  -c n : Run n copies concurrently.
- *              -e   : Turn on errno logging.
- *              -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
  */
 
-#include <sys/types.h>
-#include <signal.h>
-#include <errno.h>
-#include <sys/wait.h>
-#include "test.h"
-
-static void inthandlr();
-static void do_exit(void);
-static void setup_sigint(void);
-static void do_child_1(void);
-static void setup(void);
-static void cleanup(void);
-
-char *TCID = "waitpid08";
-int TST_TOTAL = 1;
-volatile int intintr;
-static int fail;
-
-#define	MAXKIDS	8
-
-#ifdef UCLINUX
-static char *argv0;
-static void do_child_2_uclinux(void);
-#endif
-
-int main(int argc, char **argv)
-{
-	int lc;
-
-	int status;
-	int pid;
-
-	tst_parse_opts(argc, argv, NULL, NULL);
-
-#ifdef UCLINUX
-	argv0 = argv[0];
-
-	maybe_run_child(&do_child_1, "n", 1);
-	maybe_run_child(&do_child_2_uclinux, "n", 2);
-#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;
-		fail = 0;
-
-		pid = FORK_OR_VFORK();
-		if (pid < 0) {
-			tst_resm(TFAIL, "Fork Failed, may be OK under stress");
-
-		} else if (pid == 0) {
-			/*
-			 * Child:
-			 * Set up to catch SIGINT.
-			 * The kids will wait till a SIGINT has been received
-			 * before they proceed.
-			 */
-#ifdef UCLINUX
-			if (self_exec(argv[0], "n", 1) < 0) {
-				tst_resm(TINFO, "self_exec failed");
-				exit(pid);
-			}
-#else
-			do_child_1();
-#endif
-		} else {	/* parent */
-			waitpid(pid, &status, 0);
-			if (WEXITSTATUS(status) != 0) {
-				tst_resm(TFAIL, "child returned bad status");
-				fail = 1;
-			}
-			if (fail)
-				tst_resm(TFAIL, "%s FAILED", TCID);
-			else
-				tst_resm(TPASS, "%s PASSED", TCID);
-		}
-	}
-
-	cleanup();
-	tst_exit();
-}
-
-/*
- * setup_sigint()
- *	Sets up a SIGINT handler
- */
-static void setup_sigint(void)
-{
-	if ((sig_t) signal(SIGINT, inthandlr) == SIG_ERR) {
-		tst_resm(TFAIL, "signal SIGINT failed. " "errno = %d", errno);
-		exit(-1);
-	}
-}
+#include "waitpid_common.h"
 
 static void do_child_1(void)
 {
-	int kid_count, fork_kid_pid[MAXKIDS];
-	int ret_val;
-	int i, j, k, found;
-	int group1, group2;
-	int wait_kid_pid[MAXKIDS], status;
-
-	setup_sigint();
-
-	group1 = getpgrp();
-
-	for (kid_count = 0; kid_count < MAXKIDS; kid_count++) {
-		if (kid_count == (MAXKIDS / 2))
-			group2 = setpgrp();
+	pid_t pid;
+	int i;
+	int status;
 
-		intintr = 0;
-		ret_val = FORK_OR_VFORK();
-		if (ret_val == 0) {
-#ifdef UCLINUX
-			if (self_exec(argv0, "n", 2) < 0) {
-				tst_resm(TFAIL, "Fork kid %d failed. "
-					 "errno = %d", kid_count, errno);
-				exit(ret_val);
-			}
-#else
-			do_exit();
-#endif
-		}
+	for (i = 0; i < MAXKIDS; i++) {
+		if (i == (MAXKIDS / 2))
+			SAFE_SETPGID(0, 0);
 
-		if (ret_val < 0) {
-			tst_resm(TFAIL, "Fork kid %d failed. "
-				 "errno = %d", kid_count, errno);
-			exit(ret_val);
-		}
+		pid = SAFE_FORK();
+		if (pid == 0)
+			do_exit(0);
 
-		/* parent */
-		fork_kid_pid[kid_count] = ret_val;
+		fork_kid_pid[i] = pid;
 	}
 
 	/* Check that waitpid with WNOHANG|WUNTRACED returns
 	 * zero
 	 */
-	ret_val = waitpid(-1, &status, WNOHANG | WUNTRACED);
-	if (ret_val != 0) {
-		tst_resm(TFAIL, "Waitpid returned wrong value");
-		tst_resm(TFAIL, "Expected 0 got %d", ret_val);
-		fail = 1;
-	}
-#ifdef UCLINUX
-	/* Give the kids a chance to setup SIGINT again, since this is
-	 * cleared by exec().
-	 */
-	sleep(3);
-#endif
-
-	/* Now send all the kids a SIGINT to tell them to
-	 * proceed
-	 */
-	for (i = 0; i < MAXKIDS; i++) {
-		if (kill(fork_kid_pid[i], SIGINT) < 0) {
-			tst_brkm(TFAIL, NULL, "Kill of child %d "
-				 "failed, errno = %d", i, errno);
-		}
+	pid = waitpid(-1, &status, WNOHANG | WUNTRACED);
+	if (pid != 0) {
+		tst_res(TFAIL,
+			"waitpid(WNOHANG | WUNTRACED) returned %d, expected 0",
+			pid);
+		return;
 	}
 
-	/*
-	 * Wait till all kids have terminated.  Stash away their
-	 * pid's in an array.
-	 */
-	kid_count = 0;
-	errno = 0;
-	while (((ret_val = waitpid(-1, &status, WUNTRACED)) !=
-		-1) || (errno == EINTR)) {
-		if (ret_val == -1)
-			continue;
+	TST_CHECKPOINT_WAKE2(0, MAXKIDS);
 
-		if (!WIFEXITED(status)) {
-			if (!WIFSTOPPED(status)) {
-				tst_resm(TFAIL, "Child %d did "
-					 "not stopped", ret_val);
-				fail = 1;
-			} else {
-				if (WSTOPSIG(status) != SIGSTOP) {
-					tst_resm(TFAIL,
-						 "Child %d "
-						 "exited with "
-						 "wrong status", ret_val);
-					tst_resm(TFAIL,
-						 "Expected "
-						 "SIGSTOP got %d",
-						 WSTOPSIG(status));
-					fail = 1;
-				}
-			}
-			if (kill(ret_val, SIGCONT) < 0) {
-				tst_resm(TFAIL, "Kill of child "
-					 "%d failed, errno = %d",
-					 ret_val, errno);
-				fail = 1;
-			}
-		}
-		wait_kid_pid[kid_count++] = ret_val;
-	}
-
-	/*
-	 * Check that for every entry in the fork_kid_pid array,
-	 * there is a matching pid in the wait_kid_pid array. If
-	 * not, it's an error.
-	 */
-	for (i = 0; i < kid_count; i++) {
-		found = 0;
-		for (j = 0; j < MAXKIDS; j++) {
-			if (fork_kid_pid[j] == wait_kid_pid[i]) {
-				found = 1;
-				break;
-			}
-		}
-		if (!found) {
-			tst_resm(TFAIL,
-				 "Did not find a wait_kid_pid "
-				 "for the fork_kid_pid of %d", wait_kid_pid[i]);
-			for (k = 0; k < MAXKIDS; k++) {
-				tst_resm(TFAIL,
-					 "fork_kid_pid[%d] = "
-					 "%d", k, fork_kid_pid[k]);
-			}
-			for (k = 0; k < kid_count; k++) {
-				tst_resm(TFAIL,
-					 "wait_kid_pid[%d] = "
-					 "%d", k, wait_kid_pid[k]);
-			}
-			fail = 1;
-		}
-	}
+	if (reap_children(-1, WUNTRACED, fork_kid_pid, MAXKIDS))
+		return;
 
 	/*
 	 * Check that waitpid(WUNTRACED) returns -1 when no
 	 * stopped children
 	 */
-	ret_val = waitpid(-1, &status, WUNTRACED);
-	if (ret_val != -1) {
-		tst_resm(TFAIL, "Waitpid returned wrong value.");
-		tst_resm(TFAIL, "Expected -1 got %d from "
-			 "waitpid(WUNTRACED)", ret_val);
-		fail = 1;
+	pid = waitpid(-1, &status, WUNTRACED);
+	if (pid != -1) {
+		tst_res(TFAIL, "waitpid(WUNTRACED) returned %d, expected -1",
+			pid);
+		return;
 	}
 
 	if (errno != ECHILD) {
-		tst_resm(TFAIL, "Waitpid returned wrong errno.");
-		tst_resm(TFAIL, "Expected ECHILD got %d", errno);
-		fail = 1;
+		tst_res(TFAIL, "waitpid(WUNTRACED) set errno %s, expected %s",
+			tst_strerrno(errno), tst_strerrno(ECHILD));
+		return;
 	}
 
-	exit(fail);
-}
-
-#ifdef UCLINUX
-/*
- * do_child_2_uclinux()
- *	sets up sigint handler again, then calls the normal child 2 function
- */
-static void do_child_2_uclinux(void)
-{
-	setup_sigint();
-	do_exit();
-}
-#endif
-
-static void setup(void)
-{
-	TEST_PAUSE;
-}
-
-static void cleanup(void)
-{
+	tst_res(TPASS, "Test PASSED");
 }
 
-static void inthandlr(void)
-{
-	intintr++;
-}
-
-static void wait_for_parent(void)
-{
-	int testvar;
-
-	while (!intintr)
-		testvar = 0;
-}
-
-static void do_exit(void)
-{
-	wait_for_parent();
-	exit(3);
-}
+static struct tst_test test = {
+	.tid = "waitpid08",
+	.forks_child = 1,
+	.needs_checkpoints = 1,
+	.setup = waitpid_setup,
+	.cleanup = waitpid_cleanup,
+	.test_all = waitpid_test,
+};
-- 
1.7.1


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [LTP] [PATCH V3 6/6] waitpid11: use the new API
  2016-08-04 14:16       ` [LTP] [PATCH V3 5/6] waitpid08: " Stanislav Kholmanskikh
@ 2016-08-04 14:16         ` Stanislav Kholmanskikh
  0 siblings, 0 replies; 9+ messages in thread
From: Stanislav Kholmanskikh @ 2016-08-04 14:16 UTC (permalink / raw)
  To: ltp

Signed-off-by: Stanislav Kholmanskikh <stanislav.kholmanskikh@oracle.com>
---
Changes since V2:
 * Removed reduntant tst_res(TFAIL) next to reap_children()

Changes since V1:
 * Use waitpid_setup(), waitpid_cleanup()
 * Use reap_children()

 testcases/kernel/syscalls/waitpid/waitpid11.c |  341 +++----------------------
 1 files changed, 42 insertions(+), 299 deletions(-)

diff --git a/testcases/kernel/syscalls/waitpid/waitpid11.c b/testcases/kernel/syscalls/waitpid/waitpid11.c
index 135ec56..9b51e04 100644
--- a/testcases/kernel/syscalls/waitpid/waitpid11.c
+++ b/testcases/kernel/syscalls/waitpid/waitpid11.c
@@ -1,327 +1,70 @@
 /*
+ * Copyright (c) International Business Machines  Corp., 2001
  *
- *   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 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.
  *
- *   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.
  *
- *   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
+ * History
+ *	07/2001 John George
+ *		-Ported
+ *      04/2002 wjhuie sigset cleanups
  */
 
 /*
- * NAME
- *	waitpid11.c
- *
  * DESCRIPTION
- *	Tests to see if pid's returned from fork and waitpid are same
+ *	Tests to see if pids returned from fork and waitpid are same
  *
  * ALGORITHM
  * 	Check proper functioning of waitpid with pid = -1 and arg = 0
- *
- * USAGE:  <for command-line>
- *      waitpid11 [-c n] [-t]
- *      where,  -c n : Run n copies concurrently.
- *              -t   : Turn on syscall timing.
- *
- * History
- *	07/2001 John George
- *		-Ported
- *      04/2002 wjhuie sigset cleanups
- *
- * Restrictions
- *	None
  */
 
-#include <sys/types.h>
-#include <signal.h>
-#include <errno.h>
-#include <sys/wait.h>
-#include "test.h"
-
-#define	MAXKIDS	8
+#include "waitpid_common.h"
 
-char *TCID = "waitpid11";
-int TST_TOTAL = 1;
-
-volatile int intintr;
-static void setup(void);
-static void cleanup(void);
-static void inthandlr();
-static void wait_for_parent(void);
-static void do_exit(void);
-static void setup_sigint(void);
-#ifdef UCLINUX
-static void do_exit_uclinux(void);
-#endif
-
-static int fail;
-static int fork_kid_pid[MAXKIDS];
-
-int main(int ac, char **av)
+static void do_child_1(void)
 {
-	int kid_count, ret_val, status;
-	int i, j, k, found;
-	int group1, group2;
-	int wait_kid_pid[MAXKIDS];
-	int pid;
-
-	tst_parse_opts(ac, av, NULL, NULL);
-
-#ifdef UCLINUX
-	maybe_run_child(&do_exit_uclinux, "");
-#endif
-
-	setup();
-
-	tst_count = 0;
-	fail = 0;
-
-	/*
-	 * Need to have test run from child as test driver causes
-	 * test to be a session leader and setpgrp fails.
-	 */
-
-	pid = FORK_OR_VFORK();
-	if (pid > 0) {
-		waitpid(pid, &status, 0);
-		if (WEXITSTATUS(status) != 0) {
-			tst_resm(TFAIL, "child returned bad status");
-			fail = 1;
-		}
-		if (fail)
-			tst_resm(TFAIL, "%s FAILED", TCID);
-		else
-			tst_resm(TPASS, "%s PASSED", TCID);
-		tst_exit();
-	} else if (pid < 0)
-		tst_brkm(TBROK, cleanup, "fork failed");
-
-	/*
-	 * Set up to catch SIGINT.  The kids will wait till a SIGINT
-	 * has been received before they proceed.
-	 */
-	setup_sigint();
-
-	group1 = getpgrp();
-
-	for (kid_count = 0; kid_count < MAXKIDS; kid_count++) {
-		if (kid_count == (MAXKIDS / 2))
-			group2 = setpgrp();
-
-		intintr = 0;
-		ret_val = FORK_OR_VFORK();
-		if (ret_val == 0) {
-#ifdef UCLINUX
-			if (self_exec(av[0], "") < 0)
-				tst_resm(TFAIL | TERRNO, "self_exec kid %d "
-					 "failed", kid_count);
-#else
-			do_exit();
-#endif
-		}
-
-		if (ret_val < 0)
-			tst_brkm(TBROK|TERRNO, cleanup, "Fork kid %d failed",
-				 kid_count);
-
-		/* parent */
-		fork_kid_pid[kid_count] = ret_val;
-	}
+	pid_t pid, group;
+	int i;
 
-#ifdef UCLINUX
-	/* Give the kids a chance to setup SIGINT again, since this is
-	 * cleared by exec().
-	 */
-	sleep(3);
-#endif
+	group = SAFE_GETPGID(0);
 
-	/* Now send all the kids a SIGINT to tell them to proceed */
-	for (i = 0; i < MAXKIDS; i++)
-		if (kill(fork_kid_pid[i], SIGINT) < 0)
-			tst_resm(TFAIL | TERRNO, "Kill of child %d failed", i);
+	for (i = 0; i < MAXKIDS; i++) {
+		if (i == (MAXKIDS / 2))
+			SAFE_SETPGID(0, 0);
 
-	/*
-	 * Wait till all kids have terminated.  Stash away their
-	 * pid's in an array.
-	 */
-	kid_count = 0;
-	errno = 0;
-	while (((ret_val = waitpid(0, &status, 0)) != -1) || (errno == EINTR)) {
-		if (ret_val == -1)
-			continue;
+		pid = SAFE_FORK();
+		if (pid == 0)
+			do_exit(0);
 
-		if (!WIFEXITED(status)) {
-			tst_resm(TFAIL, "Child %d did not exit "
-				 "normally", ret_val);
-			fail = 1;
-		} else {
-			if (WEXITSTATUS(status) != 3) {
-				tst_resm(TFAIL, "Child %d exited with "
-					 "wrong status", ret_val);
-				tst_resm(TFAIL, "Expected 3 got %d",
-					 WEXITSTATUS(status));
-				fail = 1;
-			}
-		}
-		wait_kid_pid[kid_count++] = ret_val;
+		fork_kid_pid[i] = pid;
 	}
 
-	/*
-	 * Check that for every entry in the fork_kid_pid array,
-	 * there is a matching pid in the wait_kid_pid array.  If
-	 * not, it's an error.
-	 */
-	for (i = 0; i < kid_count; i++) {
-		found = 0;
-		for (j = (MAXKIDS / 2); j < MAXKIDS; j++) {
-			if (fork_kid_pid[j] == wait_kid_pid[i]) {
-				found = 1;
-				break;
-			}
-		}
-		if (!found) {
-			tst_resm(TFAIL, "Did not find a fork_kid_pid "
-				 "for the wait_kid_pid of %d", wait_kid_pid[i]);
-			for (k = 0; k < MAXKIDS; k++) {
-				tst_resm(TFAIL, "fork_kid_pid[%d] = "
-					 "%d", k, fork_kid_pid[k]);
-			}
-			for (k = 0; k < kid_count; k++) {
-				tst_resm(TFAIL, "wait_kid_pid[%d] = "
-					 "%d", k, wait_kid_pid[k]);
-			}
-			fail = 1;
-		}
-	}
+	TST_CHECKPOINT_WAKE2(0, MAXKIDS);
 
-	if (kid_count != (MAXKIDS / 2)) {
-		tst_resm(TFAIL, "Wrong number of children waited on "
-			 "for pid = 0");
-		tst_resm(TFAIL, "Expected 4 got %d", kid_count);
-		fail = 1;
-	}
+	if (reap_children(0, 0, fork_kid_pid + (MAXKIDS / 2), MAXKIDS / 2))
+		return;
 
 	/* Make sure can pickup children in a diff. process group */
+	if (reap_children(-group, 0, fork_kid_pid, MAXKIDS / 2))
+		return;
 
-	kid_count = 0;
-	errno = 0;
-	while (((ret_val = waitpid(-(group1), &status, 0)) != -1) ||
-	       (errno == EINTR)) {
-		if (ret_val == -1)
-			continue;
-		if (!WIFEXITED(status)) {
-			tst_resm(TFAIL, "Child %d did not exit "
-				 "normally", ret_val);
-			fail = 1;
-		} else {
-			if (WEXITSTATUS(status) != 3) {
-				tst_resm(TFAIL, "Child %d exited with "
-					 "wrong status", ret_val);
-				tst_resm(TFAIL, "Expected 3 got %d",
-					 WEXITSTATUS(status));
-				fail = 1;
-			}
-		}
-		wait_kid_pid[kid_count++] = ret_val;
-	}
-
-	/*
-	 * Check that for every entry in the fork_kid_pid array,
-	 * there is a matching pid in the wait_kid_pid array.  If
-	 * not, it's an error.
-	 */
-	for (i = 0; i < kid_count; i++) {
-		found = 0;
-		for (j = 0; j < (MAXKIDS / 2); j++) {
-			if (fork_kid_pid[j] == wait_kid_pid[i]) {
-				found = 1;
-				break;
-			}
-		}
-		if (!found) {
-			tst_resm(TFAIL, "Did not find a fork_kid_pid "
-				 "for the wait_kid_pid of %d", wait_kid_pid[i]);
-			for (k = 0; k < MAXKIDS; k++)
-				tst_resm(TFAIL, "fork_kid_pid[%d] = "
-					 "%d", k, fork_kid_pid[k]);
-			for (k = 0; k < kid_count; k++)
-				tst_resm(TFAIL, "wait_kid_pid[%d] = "
-					 "%d", k, wait_kid_pid[k]);
-			fail = 1;
-		}
-	}
-
-	memset(fork_kid_pid, 0, sizeof(fork_kid_pid));
-
-	if (kid_count != (MAXKIDS / 2)) {
-		tst_resm(TFAIL, "Wrong number of children waited on "
-			 "for pid = 0");
-		tst_resm(TFAIL, "Expected 4 got %d", kid_count);
-		fail = 1;
-	}
-
-	if (fail)
-		tst_resm(TFAIL, "Test FAILED");
-	else
-		tst_resm(TPASS, "Test PASSED");
-
-	cleanup();
-	tst_exit();
+	tst_res(TPASS, "Test PASSED");
 }
 
-static void setup_sigint(void)
-{
-	if (signal(SIGINT, inthandlr) == SIG_ERR)
-		tst_brkm(TFAIL | TERRNO, NULL, "signal SIGINT failed");
-}
-
-static void setup(void)
-{
-	TEST_PAUSE;
-}
-
-static void cleanup(void)
-{
-	int i;
-
-	for (i = 0; i < MAXKIDS; i++) {
-		if (fork_kid_pid[i] > 0)
-			kill(fork_kid_pid[i], SIGKILL);
-	}
-}
-
-static void inthandlr(void)
-{
-	intintr++;
-}
-
-static void wait_for_parent(void)
-{
-	int testvar;
-
-	while (!intintr)
-		testvar = 0;
-}
-
-static void do_exit(void)
-{
-	wait_for_parent();
-	exit(3);
-}
-
-#ifdef UCLINUX
-static void do_exit_uclinux(void)
-{
-	setup_sigint();
-	do_exit();
-}
-#endif
+static struct tst_test test = {
+	.tid = "waitpid11",
+	.forks_child = 1,
+	.needs_checkpoints = 1,
+	.setup = waitpid_setup,
+	.cleanup = waitpid_cleanup,
+	.test_all = waitpid_test,
+};
-- 
1.7.1


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [LTP] [PATCH V3 2/6] tst_test: make reap_children() part of the test API
  2016-08-04 14:16 ` [LTP] [PATCH V3 2/6] tst_test: make reap_children() part of the test API Stanislav Kholmanskikh
  2016-08-04 14:16   ` [LTP] [PATCH V3 3/6] waitpid06: use the new API Stanislav Kholmanskikh
@ 2016-08-04 16:13   ` Cyril Hrubis
  2016-08-05  8:30     ` Cyril Hrubis
  2016-08-05  8:56     ` Stanislav Kholmanskikh
  1 sibling, 2 replies; 9+ messages in thread
From: Cyril Hrubis @ 2016-08-04 16:13 UTC (permalink / raw)
  To: ltp

Hi!
> +[source,c]
> +-------------------------------------------------------------------------------
> +#include "tst_test.h"
> +
> +void tst_reap_children(void);
> +-------------------------------------------------------------------------------
> +
> +The 'tst_reap_children()' function makes the process wait for all of its
> +children and exits with 'tst_brk(TBROK, ...)' if any of them returned
> +a non zero exit code. This function may be called only from the main
> +test process.

There is no reason to limit the function to the main test process only.
All it does it to reap all children and call tst_brk() in case that
someting went wrong.

We can for instance do:

[main test pid]
      fork()              --> [child]
      tst_reap_children()     fork()              -->[child]
                              tst_reap_children()    tst_brk(TBROK, ...)

In this case the second level child will simply call exit(TBROK), the
first level child will wait it and call exit(TBROK) because the second
level child exitted uncleanly. And finally the main test pid will exit
with TBROK, after a it's cleanup is called (if set).

And it's nearly the same in case of tst_brk(TCONF, ...) but the exit
value will be 0 and the TCONF is instead stored in the result structure
in the shared memory.

Maybe we should include this ascii art diagram in the documentation as
well.


The rest of the patchset is good, acked.

Let's commit it without the sentence that limits this function to the
main test process. I will do something about the documentation later.

-- 
Cyril Hrubis
chrubis@suse.cz

^ permalink raw reply	[flat|nested] 9+ messages in thread

* [LTP] [PATCH V3 2/6] tst_test: make reap_children() part of the test API
  2016-08-04 16:13   ` [LTP] [PATCH V3 2/6] tst_test: make reap_children() part of the test API Cyril Hrubis
@ 2016-08-05  8:30     ` Cyril Hrubis
  2016-08-05  8:56     ` Stanislav Kholmanskikh
  1 sibling, 0 replies; 9+ messages in thread
From: Cyril Hrubis @ 2016-08-05  8:30 UTC (permalink / raw)
  To: ltp

Hi!
> And it's nearly the same in case of tst_brk(TCONF, ...) but the exit
> value will be 0 and the TCONF is instead stored in the result structure
> in the shared memory.

Scratch that, the tst_brk(TCONF, ...) behaves exactly the same as
tst_brk(TBRO, ...). I.e. propagates via return value. Sorry for being
confusing.

-- 
Cyril Hrubis
chrubis@suse.cz

^ permalink raw reply	[flat|nested] 9+ messages in thread

* [LTP] [PATCH V3 2/6] tst_test: make reap_children() part of the test API
  2016-08-04 16:13   ` [LTP] [PATCH V3 2/6] tst_test: make reap_children() part of the test API Cyril Hrubis
  2016-08-05  8:30     ` Cyril Hrubis
@ 2016-08-05  8:56     ` Stanislav Kholmanskikh
  1 sibling, 0 replies; 9+ messages in thread
From: Stanislav Kholmanskikh @ 2016-08-05  8:56 UTC (permalink / raw)
  To: ltp



On 08/04/2016 07:13 PM, Cyril Hrubis wrote:
> Hi!
>> +[source,c]
>> +-------------------------------------------------------------------------------
>> +#include "tst_test.h"
>> +
>> +void tst_reap_children(void);
>> +-------------------------------------------------------------------------------
>> +
>> +The 'tst_reap_children()' function makes the process wait for all of its
>> +children and exits with 'tst_brk(TBROK, ...)' if any of them returned
>> +a non zero exit code. This function may be called only from the main
>> +test process.
> 
> There is no reason to limit the function to the main test process only.
> All it does it to reap all children and call tst_brk() in case that
> someting went wrong.
> 
> We can for instance do:
> 
> [main test pid]
>       fork()              --> [child]
>       tst_reap_children()     fork()              -->[child]
>                               tst_reap_children()    tst_brk(TBROK, ...)
> 
> In this case the second level child will simply call exit(TBROK), the
> first level child will wait it and call exit(TBROK) because the second
> level child exitted uncleanly. And finally the main test pid will exit
> with TBROK, after a it's cleanup is called (if set).
> 
> And it's nearly the same in case of tst_brk(TCONF, ...) but the exit
> value will be 0 and the TCONF is instead stored in the result structure
> in the shared memory.
> 
> Maybe we should include this ascii art diagram in the documentation as
> well.
> 
> 
> The rest of the patchset is good, acked.
> 
> Let's commit it without the sentence that limits this function to the
> main test process. I will do something about the documentation later.
> 

Thank you! Committed the series without the sentence.

^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2016-08-05  8:56 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-08-04 14:16 [LTP] [PATCH V3 1/6] tst_safe_macros: SAFE_GETPGID Stanislav Kholmanskikh
2016-08-04 14:16 ` [LTP] [PATCH V3 2/6] tst_test: make reap_children() part of the test API Stanislav Kholmanskikh
2016-08-04 14:16   ` [LTP] [PATCH V3 3/6] waitpid06: use the new API Stanislav Kholmanskikh
2016-08-04 14:16     ` [LTP] [PATCH V3 4/6] waitpid07: " Stanislav Kholmanskikh
2016-08-04 14:16       ` [LTP] [PATCH V3 5/6] waitpid08: " Stanislav Kholmanskikh
2016-08-04 14:16         ` [LTP] [PATCH V3 6/6] waitpid11: " Stanislav Kholmanskikh
2016-08-04 16:13   ` [LTP] [PATCH V3 2/6] tst_test: make reap_children() part of the test API Cyril Hrubis
2016-08-05  8:30     ` Cyril Hrubis
2016-08-05  8:56     ` Stanislav Kholmanskikh

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.