int getchild(int group, int child, int children) { int pid; pid = FORK_OR_VFORK(); if (pid < 0) { massmurder(); /* kill the kids */ tst_brkm(TBROK, cleanup, "\tFork failed (may be OK if under stress)"); tst_exit(); } else if (pid == 0) { /* child does this */ switch (children % NCHILD) { case 0: #ifdef UCLINUX if (self_exec(argv0, "nd", 1, nfiles) < 0) { massmurder(); tst_brkm(TBROK, cleanup, "\tself_exec failed"); tst_exit(); } #else dochild1(); /* create existing directories */ #endif break; /* so lint won't complain */ case 1: #ifdef UCLINUX if (self_exec(argv0, "n", 2) < 0) { massmurder(); tst_brkm(TBROK, cleanup, "\tself_exec failed"); tst_exit(); } #else dochild2(); /* remove nonexistant directories */ #endif break; case 2: #ifdef UCLINUX if (self_exec(argv0, "nd", 3, group) < 0) { massmurder(); tst_brkm(TBROK, cleanup, "\tself_exec failed"); tst_exit(); } #else dochild3(group); /* create/delete directories */ #endif break; default: tst_brkm(TFAIL, cleanup, "Test not inplemented for child %d", child); exit(1); break; } exit(1); /* If child gets here, something wrong */ } pidlist[children] = pid; return 0; }
int runtest(void) { int i, j; int count, child, status; char tmpdir[MAXPATHLEN]; /* Create permanent directories with holes in directory structure */ for (j = 0; j < nfiles; j++) { sprintf(tmpdir, DIR_NAME, j); TEST(mkdir(tmpdir, MODE_RWX)); if (TEST_RETURN < 0) { tst_brkm(TFAIL, cleanup, "Error creating permanent directories, ERRNO = %d", TEST_ERRNO); } if ((j % NCHILD) != 0) { if (rmdir(tmpdir) < 0) { tst_brkm(TFAIL, cleanup, "Error removing directory, ERRNO = %d", errno); } } } parent_pid = getpid(); /* allocate space for list of child pid's */ if ((pidlist = malloc((child_groups * NCHILD) * sizeof(int))) == NULL) { tst_brkm(TWARN, NULL, "\tMalloc failed (may be OK if under stress)"); } child_count = 0; for (j = 0; j < child_groups; j++) { for (i = 0; i < NCHILD; i++) { getchild(j, i, child_count); child_count++; } } /* If signal already received, skip to cleanup */ if (!sigchld && !sigterm) { if (test_time) { /* To get out of sleep if signal caught */ if (!setjmp(env_buf)) { jump++; sleep(test_time); } } else { pause(); } } /* Reset signals since we are about to clean-up and to avoid * problem with wait call * $ * */ if (signal(SIGTERM, SIG_IGN) == SIG_ERR) { tst_brkm(TFAIL, cleanup, "Error resetting SIGTERM signal, ERRNO = %d", errno); } if (signal(SIGCLD, SIG_DFL) == SIG_ERR) { tst_brkm(TFAIL, cleanup, "Error resetting SIGCLD signal, ERRNO = %d", errno); } if (test_time) { sleep(test_time); } /* Clean up children */ massmurder(); /* * Watch children finish and show returns. */ count = 0; while (1) { if ((child = wait(&status)) > 0) { if (status != 0) { tst_brkm(TWARN, NULL, "\tChild{%d} exited status = %0x", child, status); } count++; } else { if (errno != EINTR) { break; } tst_resm(TINFO, "\tSignal detected during wait"); } } /* * Make sure correct number of children exited. */ if (count != child_count) { tst_resm(TWARN, "\tWrong number of children waited on!"); tst_brkm(TWARN, NULL, "\tSaw %d, expected %d", count, NCHILD); } /* Check for core file in test directory. */ if (access("core", 0) == 0) { tst_brkm(TWARN, NULL, "\tCore file found in test directory."); } /* Remove expected files */ for (j = 0; j < nfiles; j += NCHILD) { sprintf(tmpdir, DIR_NAME, j); if (rmdir(tmpdir) < 0) { tst_brkm(TWARN, NULL, "\tError removing expected directory, ERRNO = %d", errno); } } tst_resm(TPASS, "PASS"); return 0; }