static void test_clone_thread(int t) { pid_t child; int i, status; fflush(stdout); child = FORK_OR_VFORK(); switch (child) { case 0: tgid = ltp_syscall(__NR_getpid); tst_result = -1; clone_child(&test_cases[t], 0); for (i = 0; i < 5000; i++) { sched_yield(); usleep(1000); if (tst_result != -1) break; } ltp_syscall(__NR_exit, tst_result); case -1: tst_brkm(TBROK | TERRNO, NULL, "test_clone_thread fork"); default: status = wait4child(child); if (status == 0) { tst_resm(TPASS, "test %s", test_cases[t].name); } else { tst_resm(TFAIL, "test %s, status: %d", test_cases[t].name, status); } }; }
static void test_clone_stopped(int t) { int i; int status; int flag; pid_t child; stopped_flag = 0; child = clone_child(&test_cases[t], 1); /* give the kernel scheduler chance to run the CLONE_STOPPED thread*/ for (i = 0; i < 100; i++) { sched_yield(); usleep(1000); } flag = stopped_flag; if (kill(child, SIGCONT) != 0) tst_brkm(TBROK | TERRNO, cleanup, "kill SIGCONT failed"); status = wait4child(child); if (status == 0 && flag == 0) { tst_resm(TPASS, "test %s", test_cases[t].name); } else { tst_resm(TFAIL, "test %s, status: %d, flag: %d", test_cases[t].name, status, flag); } }
static void test_clone_parent(int t) { int status; pid_t child; fflush(stdout); child = FORK_OR_VFORK(); switch (child) { case 0: parent_ppid = getppid(); clone_child(&test_cases[t], 0); exit(0); case -1: tst_brkm(TBROK | TERRNO, NULL, "test_clone_parent fork"); default: status = wait4child(child); if (status == 0) { /* wait for CLONE_PARENT child */ status = wait4child(-1); if (status == 0) { tst_resm(TPASS, "test %s", test_cases[t].name); } else { tst_resm(TFAIL, "test %s, status: %d", test_cases[t].name, status); } } else { tst_resm(TFAIL, "test %s, status: %d", test_cases[t].name, status); } }; }
static int child(void *_arg) { char buf[sizeof(TEST_STRING)]; pid_t pid, pid2; int status; pid = clone_child(child2, CLONE_FILES); if (pid < 0) return 1; pid2 = clone_child(child3, 0); if (pid < 0) return 1; forked(); test_waitsig(); kill(pid2, SIGTERM); kill(pid, SIGTERM); waitpid(pid2, &status, 0); if (status) { fail("The child3 returned %d\n", status); return 1; } waitpid(pid, &status, 0); if (status) { fail("The child2 returned %d\n", status); return 1; } if (read(TEST_FD, buf, sizeof(TEST_STRING)) != sizeof(TEST_STRING)) { pr_perror("Unable to read from %d", TEST_FD); return 1; } if (close(TEST_FD) == -1) { pr_perror("Unable to close(%d)", TEST_FD); return 1; } return 0; }
static void test_clone_tid(int t) { int status; pid_t child; child = clone_child(&test_cases[t], 1); status = wait4child(child); if (status == 0) { tst_resm(TPASS, "test %s", test_cases[t].name); } else { tst_resm(TFAIL, "test %s, status: %d", test_cases[t].name, status); } }
int main(int argc, char ** argv) { int status; pid_t pid, pid2; int fd, i; test_init(argc, argv); pid = clone_child(child, CLONE_FILES); if (pid < 0) return 1; pid2 = clone_child(child2, CLONE_FILES); if (pid2 < 0) return 1; test_daemon(); test_waitsig(); fd = open(filename, O_RDWR | O_CREAT, 0666); if (fd == -1) { err("Can't open /dev/zero\n"); return -1; } for (i = 0; i < 3; i++) if (write(fd, TEST_STRING, sizeof(TEST_STRING)) != sizeof(TEST_STRING)) { err("Unable to write a test string\n"); return -1; } fd = dup2(fd, TEST_FD); if (fd == -1) { err("Can't dup fd to %d\n", fd, TEST_FD); return -1; } lseek(fd, 0, SEEK_SET); kill(pid2, SIGTERM); waitpid(pid2, &status, 0); kill(pid, SIGTERM); if (status) { fail("The child returned %d\n", status); return 1; } waitpid(pid, &status, 0); if (status) { fail("The child returned %d\n", status); return 1; } if (close(TEST_FD) == 0) { fail("%d was not closed\n", TEST_FD); return 1; } pass(); return 0; }