__pid_t __libc_waitpid (__pid_t pid, int *stat_loc, int options) { __idtype_t idtype; __pid_t tmp_pid = pid; __siginfo_t infop; if (pid <= WAIT_MYPGRP) { if (pid == WAIT_ANY) { /* Request the status for any child. */ idtype = P_ALL; } else if (pid == WAIT_MYPGRP) { /* Request the status for any child process that has a pgid that's equal to that of our parent. */ tmp_pid = __getpgid (0); idtype = P_PGID; } else /* PID < -1 */ { /* Request the status for any child whose pgid is equal to the absolute value of PID. */ tmp_pid = pid & ~0; /* XXX not pseudo-insn */ idtype = P_PGID; } } else { /* Request the status for the child whose pid is PID. */ idtype = P_PID; } if (__waitid (idtype, tmp_pid, &infop, options | WEXITED | WTRAPPED) < 0) return -1; switch (infop.__code) { case EXITED: *stat_loc = W_EXITCODE (infop.__status, 0); break; case STOPPED: case TRAPPED: *stat_loc = W_STOPCODE (infop.__status); break; case KILLED: /* Don't know what to do with continue, since it isn't documented. Putting it here seemed the right place though. */ case CONTINUED: *stat_loc = infop.__status; /* FALLTHROUGH */ case CORED: *stat_loc |= WCOREFLAG; break; } /* Return the PID out of the INFOP structure instead of the one we were called with, to account for cases of being called with -1 to signify any PID. */ return infop.__pid; }
int main(int ac, char **av) { id_t pgid; id_t id1, id2, id3; siginfo_t infop; int i = 0; int lc; char *msg; msg = parse_opts(ac, av, NULL, NULL); if (msg != NULL) { tst_brkm(TBROK, NULL, "OPTION PARSING ERROR - %s", msg); tst_exit(); } setup(); for (lc = 0; TEST_LOOPING(lc); ++lc) { tst_count = 0; for (testno = 0; testno < TST_TOTAL; ++testno) { TEST(waitid(P_ALL, 0, &infop, WNOHANG)); if (TEST_RETURN == -1) tst_resm(TPASS, "Success1 ... -1 is returned. error is %d.", TEST_ERRNO); else { tst_resm(TFAIL, "%s Failed1 ...", TCID); } /* option == WEXITED | WCONTINUED | WSTOPPED | WNOHANG | WNOWAIT */ TEST(id1 = fork()); if (TEST_RETURN == 0) { tst_resm(TINFO, "I'm a child 1,my id is %d,gpid is %d", id1 = getpid(), __getpgid(0)); sleep(1); exit(5); } TEST(id2 = fork()); if (TEST_RETURN == 0) { sleep(3); tst_resm(TINFO, "I'm a child 2,my id is %d,gpid is %d", id2 = getpid(), __getpgid(0)); exit(7); } TEST(id3 = fork()); if (TEST_RETURN == 0) { sleep(2); TEST(kill(id2, SIGCONT)); tst_resm(TINFO, "I'm a child 3,my id is %d,gpid is %d", id3 = getpid(), __getpgid(0)); exit(6); } TEST(waitid(P_ALL, 0, &infop, WNOHANG | WEXITED)); if (TEST_RETURN == 0) tst_resm(TPASS, "Success 2 ...0 is returned.. error is %d.", TEST_ERRNO); else { tst_resm(TFAIL | TTERRNO, "%s Failed 2", TCID); tst_exit(); } tst_resm(TINFO, "I'm a Parent,my id is %d,gpid is %d", getpid(), pgid = __getpgid(0)); TEST(waitid(P_PGID, pgid, &infop, WEXITED)); if (TEST_RETURN == 0) { tst_resm(TPASS, "Success3 ... 0 is returned."); tst_resm(TINFO, "si_pid = %d ; si_code = %d ; si_status = %d", infop.si_pid, infop.si_code, infop.si_status); } else { tst_resm(TFAIL | TTERRNO, "Fail3 ... %ld is returned", TEST_RETURN); tst_exit(); } TEST(kill(id2, SIGSTOP)); TEST(i = waitid(P_PID, id2, &infop, WSTOPPED | WNOWAIT)); if (TEST_RETURN == 0) { /*EINVAL*/ tst_resm(TINFO, "si_pid = %d, si_code = %d, si_status = %d", infop.si_pid, infop.si_code, infop.si_status); tst_resm(TPASS, "Success4 ... 0 is returned"); } else { tst_resm(TFAIL | TTERRNO, "Fail4 ... %d is returned", i); tst_exit(); } TEST(waitid(P_PID, id3, &infop, WEXITED)); if (TEST_RETURN == 0) { /*NOCHILD*/ tst_resm(TINFO, "si_pid = %d, si_code = %d, si_status = %d", infop.si_pid, infop.si_code, infop.si_status); tst_resm(TPASS, "Success5 ... 0 is returned"); } else { tst_resm(TFAIL | TTERRNO, "Fail5 ... %ld is returned", TEST_RETURN); tst_exit(); } TEST(i = waitid(P_PID, id2, &infop, WCONTINUED)); if (TEST_RETURN == 0) { /*EINVAL*/ tst_resm(TINFO, "si_pid = %d, si_code = %d, si_status = %d", infop.si_pid, infop.si_code, infop.si_status); tst_resm(TPASS, "Success6 ... 0 is returned"); } else { tst_resm(TFAIL | TTERRNO, "Fail6 ... %d is returned", i); tst_exit(); } sleep(3); } } cleanup(); tst_exit(); }
/* Get the process group ID of the calling process. */ pid_t getpgrp (void) { return __getpgid (0); }