[LTP] [PATCH] waitpid/waitpid10: break test if fork failed
Han Pingtian
hanpt@linux.vnet.ibm.com
Thu May 12 03:30:08 CEST 2016
On Mon, Apr 25, 2016 at 03:41:46PM +0800, Han Pingtian wrote:
> From cbb8532924543c7b4b885abe56beaa8f927af33f Mon Sep 17 00:00:00 2001
> From: Han Pingtian <hanpt@linux.vnet.ibm.com>
> Date: Wed, 13 Apr 2016 11:25:20 +0800
> Subject: [PATCH] waitpid/waitpid10: fix broken test case
>
> Using standard -I option to set runtime and get rid of alarm().
> Optimizing the code of children propagating. Change to using
> SIGUSR1 for communication between children and parent. Break
> test if fork() failed, or a lot of processes will be killed
> when -1 passed as pid to kill().
>
Could you please take a look at this patch? Thanks.
> Signed-off-by: Han Pingtian <hanpt@linux.vnet.ibm.com>
> ---
> runtest/syscalls | 2 +-
> testcases/kernel/syscalls/waitpid/waitpid10.c | 355 +++++++++-----------------
> 2 files changed, 122 insertions(+), 235 deletions(-)
>
> diff --git a/runtest/syscalls b/runtest/syscalls
> index ca922e6..106941a 100644
> --- a/runtest/syscalls
> +++ b/runtest/syscalls
> @@ -1399,7 +1399,7 @@ waitpid06 waitpid06
> waitpid07 waitpid07
> waitpid08 waitpid08
> waitpid09 waitpid09
> -waitpid10 waitpid10 5
> +waitpid10 waitpid10 -I 5
> waitpid11 waitpid11
> waitpid12 waitpid12
> waitpid13 waitpid13
> diff --git a/testcases/kernel/syscalls/waitpid/waitpid10.c b/testcases/kernel/syscalls/waitpid/waitpid10.c
> index 6378ab9..238e9bd 100644
> --- a/testcases/kernel/syscalls/waitpid/waitpid10.c
> +++ b/testcases/kernel/syscalls/waitpid/waitpid10.c
> @@ -33,8 +33,8 @@
> * kids and remove the directory.
> *
> * USAGE: <for command-line>
> - * waitpid10 [-c n] [-i n] [-I x] [-P x] [-t]
> - * where, -c n : Run n copies concurrently.
> + * waitpid10 [-i n] [-I x] [-P x] [-t]
> + * where,
> * -i n : Execute test n times.
> * -I x : Execute test for x seconds.
> * -P x : Pause for x seconds between iterations.
> @@ -68,13 +68,11 @@
> char *TCID = "waitpid10";
> int TST_TOTAL = 1;
>
> -static int alrmintr;
> volatile int intintr;
>
> static void setup(void);
> static void cleanup(void);
> static void inthandlr();
> -static void alrmhandlr();
> static void wait_for_parent(void);
> static void do_exit(void);
> static void do_compute(void);
> @@ -83,6 +81,7 @@ static void do_sleep(void);
> static void do_mkdir(void);
>
> static int fail;
> +static int fork_kid_pid[MAXKIDS];
>
> #ifdef UCLINUX
> static char *argv0;
> @@ -92,8 +91,7 @@ int main(int ac, char **av)
> {
> int kid_count, ret_val, status, nkids;
> int i, j, k, found;
> - int fork_kid_pid[MAXKIDS], wait_kid_pid[MAXKIDS];
> - int runtime; /* time(sec) to run this process */
> + int wait_kid_pid[MAXKIDS];
>
> int lc;
>
> @@ -109,18 +107,6 @@ int main(int ac, char **av)
> maybe_run_child(&do_mkdir, "n", 5);
> #endif
>
> - /*
> - * process the arg -- If there is one arg, it is the
> - * number of seconds to run. If there is no arg the program
> - * defaults to 60 sec runtime.
> - */
> - if (ac == 2) {
> - if (sscanf(av[1], "%d", &runtime) != 1)
> - tst_resm(TFAIL, "%s is an invalid argument", av[1]);
> - } else {
> - runtime = 60;
> - }
> -
> setup();
>
> for (lc = 0; TEST_LOOPING(lc); lc++) {
> @@ -128,257 +114,144 @@ int main(int ac, char **av)
> tst_count = 0;
> fail = 0;
>
> - if (signal(SIGALRM, alrmhandlr) == SIG_ERR) {
> - tst_resm(TFAIL, "signal SIGALRM failed. errno = %d",
> - errno);
> -
> - }
> - alrmintr = 0;
> -
> /*
> - * Set up to catch SIGINT. The kids will wait till a SIGINT
> - * has been received before they proceed.
> + * Fork 8 kids. There will be 4 sets of 2 processes
> + * doing the same thing. Save all kid pid's in an
> + * array for future use. The kids will first wait for
> + * the parent to send SIGINT. Then will proceed to
> + * their assigned tasks.
> + */
> + kid_count = 0;
> + /*
> + * Clearing the intinitr flag here for all the children.
> + * So that we may not miss any signals !
> */
> - if (signal(SIGINT, inthandlr) == SIG_ERR) {
> - tst_resm(TFAIL, "signal SIGINT failed. errno = %d",
> - errno);
> -
> - }
> intintr = 0;
> -
> - /* Turn on the real time interval timer. */
> - if ((alarm(runtime)) < 0)
> - tst_resm(TFAIL, "alarm failed. errno = %d", errno);
> -
> - /* Run the test over and over until the timer expires */
> - for (;;) {
> - if (alrmintr)
> - break;
> -
> - /*
> - * Fork 8 kids. There will be 4 sets of 2 processes
> - * doing the same thing. Save all kid pid's in an
> - * array for future use. The kids will first wait for
> - * the parent to send SIGINT. Then will proceed to
> - * their assigned tasks.
> - */
> - kid_count = 0;
> - /*
> - * Clearing the intinitr flag here for all the children.
> - * So that we may not miss any signals !
> - */
> - intintr = 0;
> + for (i = 0; i < MAXKIDS; i++) {
> ret_val = FORK_OR_VFORK();
> - if (ret_val == 0) { /* child 0 */
> -#ifdef UCLINUX
> - if (self_exec(argv0, "n", 1) < 0)
> - tst_resm(TFAIL, "self_exec 0 failed");
> -#else
> - do_exit();
> -#endif
> - }
> - if (ret_val < 0) {
> - tst_resm(TFAIL, "Fork kid 0 failed. errno = "
> - "%d", errno);
> -
> - }
> -
> - /* parent */
> - fork_kid_pid[kid_count++] = ret_val;
> + if (ret_val < 0)
> + tst_brkm(TBROK|TERRNO, cleanup,
> + "Fork kid %d failed.", i);
>
> - ret_val = FORK_OR_VFORK();
> - if (ret_val == 0) { /* child 1 */
> + if (ret_val == 0) { /* child */
> + if (i == 0 || i == 1) {
> #ifdef UCLINUX
> - if (self_exec(argv0, "n", 1) < 0)
> - tst_resm(TFAIL, "self_exec 1 failed");
> + if (self_exec(argv0, "n", 1) < 0)
> + tst_brkm(TBROK|TERRNO, cleanup,
> + "self_exec %d failed",
> + i);
> #else
> - do_exit();
> + do_exit();
> #endif
> - }
> - if (ret_val < 0) {
> - tst_resm(TFAIL, "Fork kid 1 failed. errno = "
> - "%d", errno);
> -
> - }
> -
> - /* parent */
> - fork_kid_pid[kid_count++] = ret_val;
> + }
>
> - ret_val = FORK_OR_VFORK();
> - if (ret_val == 0) { /* child 2 */
> + if (i == 2 || i == 3) {
> #ifdef UCLINUX
> - if (self_exec(argv0, "n", 2) < 0)
> - tst_resm(TFAIL, "self_exec 2 failed");
> + if (self_exec(argv0, "n", 2) < 0)
> + tst_brkm(TBROK|TERRNO, cleanup,
> + "self_exec %d failed",
> + i);
> #else
> - do_compute();
> + do_compute();
> #endif
> - }
> - if (ret_val < 0) {
> - tst_resm(TFAIL, "Fork kid 2 failed. errno = "
> - "%d", errno);
> -
> - }
> -
> - /* parent */
> - fork_kid_pid[kid_count++] = ret_val;
> + }
>
> - ret_val = FORK_OR_VFORK();
> - if (ret_val == 0) { /* child 3 */
> + if (i == 4 || i == 5) {
> #ifdef UCLINUX
> - if (self_exec(argv0, "n", 2) < 0)
> - tst_resm(TFAIL, "self_exec 3 failed");
> + if (self_exec(argv0, "n", 3) < 0)
> + tst_brkm(TBROK|TERRNO, cleanup,
> + "self_exec %d failed",
> + i);
> #else
> - do_compute();
> + do_fork();
> #endif
> - }
> - if (ret_val < 0) {
> - tst_resm(TFAIL, "Fork kid 3 failed. errno = "
> - "%d", errno);
> -
> - }
> -
> - /* parent */
> - fork_kid_pid[kid_count++] = ret_val;
> + }
>
> - ret_val = FORK_OR_VFORK();
> - if (ret_val == 0) { /* child 4 */
> + if (i == 6 || i == 7) {
> #ifdef UCLINUX
> - if (self_exec(argv0, "n", 3) < 0)
> - tst_resm(TFAIL, "self_exec 4 failed");
> + if (self_exec(argv0, "n", 4) < 0)
> + tst_brkm(TBROK|TERRNO, cleanup,
> + "self_exec %d failed",
> + i);
> #else
> - do_fork();
> + do_sleep();
> #endif
> - }
> - if (ret_val < 0) {
> - tst_resm(TFAIL, "Fork kid 4 failed. errno = "
> - "%d", errno);
> -
> - }
>
> - /* parent */
> - fork_kid_pid[kid_count++] = ret_val;
> -
> - ret_val = FORK_OR_VFORK();
> - if (ret_val == 0) { /* child 5 */
> -#ifdef UCLINUX
> - if (self_exec(argv0, "n", 3) < 0)
> - tst_resm(TFAIL, "self_exec 5 failed");
> -#else
> - do_fork();
> -#endif
> - }
> - if (ret_val < 0) {
> - tst_resm(TFAIL, "Fork kid 5 failed. errno = "
> - "%d", errno);
> + }
>
> }
>
> /* parent */
> fork_kid_pid[kid_count++] = ret_val;
> + }
>
> - ret_val = FORK_OR_VFORK();
> - if (ret_val == 0) { /* child 6 */
> -#ifdef UCLINUX
> - if (self_exec(argv0, "n", 4) < 0)
> - tst_resm(TFAIL, "self_exec 6 failed");
> -#else
> - do_sleep();
> -#endif
> - }
> - if (ret_val < 0) {
> - tst_resm(TFAIL, "Fork kid 6 failed. errno = "
> - "%d", errno);
> -
> - }
> -
> - /* parent */
> - fork_kid_pid[kid_count++] = ret_val;
> + nkids = kid_count;
>
> - ret_val = FORK_OR_VFORK();
> - if (ret_val == 0) { /* child 7 */
> -#ifdef UCLINUX
> - if (self_exec(argv0, "n", 4) < 0)
> - tst_resm(TFAIL, "self_exec 7 failed");
> -#else
> - do_sleep();
> -#endif
> - }
> - if (ret_val < 0) {
> - tst_resm(TFAIL, "Fork kid 7 failed. errno = "
> - "%d", errno);
> + /*
> + * Now send all the kids a SIGUSR1 to tell them to
> + * proceed. We sleep for a while first to allow the
> + * children to initialize their "intintr" variables
> + * and get set up.
> + */
> + sleep(15);
>
> + for (i = 0; i < nkids; i++) {
> + if (kill(fork_kid_pid[i], SIGUSR1) < 0) {
> + tst_brkm(TBROK|TERRNO, cleanup, "Kill of child "
> + "%d failed", i);
> }
> + }
>
> - /* parent */
> - fork_kid_pid[kid_count++] = ret_val;
> -
> - nkids = kid_count;
> -
> - /*
> - * Now send all the kids a SIGINT to tell them to
> - * proceed. We sleep for a while first to allow the
> - * children to initialize their "intintr" variables
> - * and get set up.
> - */
> - sleep(15);
> -
> - for (i = 0; i < nkids; i++) {
> - if (kill(fork_kid_pid[i], SIGINT) < 0) {
> - tst_resm(TFAIL, "Kill of child %d "
> - "failed, errno = %d", i,
> - errno);
> - }
> + /* Wait till all kids have terminated. */
> + kid_count = 0;
> + errno = 0;
> + for (i = 0; i < nkids; i++) {
> + while (((ret_val = waitpid(fork_kid_pid[i],
> + &status, 0)) != -1)
> + || (errno == EINTR)) {
> + if (ret_val == -1)
> + continue;
> +
> + wait_kid_pid[kid_count++] = ret_val;
> }
> + }
>
> - /* Wait till all kids have terminated. */
> - kid_count = 0;
> - errno = 0;
> - for (i = 0; i < nkids; i++) {
> - while (((ret_val = waitpid(fork_kid_pid[i],
> - &status, 0)) != -1)
> - || (errno == EINTR)) {
> - if (ret_val == -1)
> - continue;
> -
> - 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.
> + */
> + for (i = 0; i < MAXKIDS; i++) {
> + found = 0;
> + for (j = 0; j < MAXKIDS; j++) {
> + if (fork_kid_pid[i] == wait_kid_pid[j]) {
> + found = 1;
> + break;
> }
> }
> -
> - /*
> - * Check that for every entry in the fork_kid_pid
> - * array, there is a matching pid in the
> - * wait_kid_pid array.
> - */
> - for (i = 0; i < MAXKIDS; i++) {
> - found = 0;
> - for (j = 0; j < MAXKIDS; j++) {
> - if (fork_kid_pid[i] == wait_kid_pid[j]) {
> - found = 1;
> - break;
> - }
> + if (!found) {
> + tst_resm(TFAIL, "Did not find a "
> + "wait_kid_pid for the "
> + "fork_kid_pid of %d",
> + fork_kid_pid[i]);
> + for (k = 0; k < nkids; k++) {
> + tst_resm(TFAIL,
> + "fork_kid_pid[%d] = "
> + "%d", k,
> + fork_kid_pid[k]);
> }
> - if (!found) {
> - tst_resm(TFAIL, "Did not find a "
> - "wait_kid_pid for the "
> - "fork_kid_pid of %d",
> - fork_kid_pid[i]);
> - for (k = 0; k < nkids; 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;
> + 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));
> +
> /* Kill kids and remove file from do_mkdir */
> rmdir("waitpid14.ttt.ttt");
>
> @@ -394,18 +267,32 @@ int main(int ac, char **av)
>
> static void setup(void)
> {
> + struct sigaction act;
> +
> tst_sig(FORK, DEF_HANDLER, cleanup);
>
> TEST_PAUSE;
> +
> + act.sa_handler = inthandlr;
> + act.sa_flags = SA_RESTART;
> + sigemptyset(&act.sa_mask);
> +
> + if (sigaction(SIGUSR1, &act, NULL) < 0)
> + tst_brkm(TBROK|TERRNO, cleanup,
> + "sigaction(SIGUSR1, ...) failed");
> +
> + intintr = 0;
> +
> }
>
> static void cleanup(void)
> {
> -}
> + int i;
>
> -static void alrmhandlr(void)
> -{
> - alrmintr++;
> + for (i = 0; i < MAXKIDS; i++) {
> + if (fork_kid_pid[i] > 0)
> + kill(fork_kid_pid[i], SIGKILL);
> + }
> }
>
> static void inthandlr(void)
> @@ -462,7 +349,7 @@ static void do_fork(void)
> for (i = 0; i < 50; i++) {
> fork_pid = FORK_OR_VFORK();
> if (fork_pid < 0) {
> - tst_brkm(TFAIL, NULL, "Fork failed");
> + tst_brkm(TBROK|TERRNO, NULL, "Fork failed");
> }
> if (fork_pid == 0) {
> #ifdef UCLINUX
> --
> 1.9.3
>
>
> --
> Mailing list info: https://lists.linux.it/listinfo/ltp
More information about the ltp
mailing list