From: Jan S. <jst...@re...> - 2013-05-17 08:59:37
|
Remove useless comments, convert spaces to tabs and fix long lines. Signed-off-by: Jan Stancek <jst...@re...> --- testcases/kernel/syscalls/waitid/waitid02.c | 104 +++++++++------------------ 1 files changed, 33 insertions(+), 71 deletions(-) diff --git a/testcases/kernel/syscalls/waitid/waitid02.c b/testcases/kernel/syscalls/waitid/waitid02.c index 98bf3ea..e265c32 100644 --- a/testcases/kernel/syscalls/waitid/waitid02.c +++ b/testcases/kernel/syscalls/waitid/waitid02.c @@ -11,9 +11,9 @@ /* 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; if not, write to the Free Software */ -/* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +/* 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 */ /* */ /******************************************************************************/ /******************************************************************************/ @@ -54,55 +54,16 @@ char *TCID = "waitid02"; int testno; int TST_TOTAL = 4; -/* Extern Global Functions */ -/******************************************************************************/ -/* */ -/* Function: cleanup */ -/* */ -/* Description: Performs all one time clean up for this test on successful */ -/* completion, premature exit or failure. Closes all temporary */ -/* files, removes all temporary directories exits the test with */ -/* appropriate return code by calling tst_exit() function. */ -/* */ -/* Input: None. */ -/* */ -/* Output: None. */ -/* */ -/* Return: On failure - Exits calling tst_exit(). Non '0' return code. */ -/* On success - Exits calling tst_exit(). With '0' return code. */ -/* */ -/******************************************************************************/ -extern void cleanup() +static void cleanup(void) { - TEST_CLEANUP; tst_rmdir(); tst_exit(); } -/* Local Functions */ -/******************************************************************************/ -/* */ -/* Function: setup */ -/* */ -/* Description: Performs all one time setup for this test. This function is */ -/* typically used to capture signals, create temporary dirs */ -/* and temporary files that may be used in the course of this */ -/* test. */ -/* */ -/* Input: None. */ -/* */ -/* Output: None. */ -/* */ -/* Return: On failure - Exits by calling cleanup(). */ -/* On success - returns 0. */ -/* */ -/******************************************************************************/ -void setup() +static void setup(void) { - /* Capture signals if any */ - /* Create temporary directories */ TEST_PAUSE; tst_tmpdir(); } @@ -112,7 +73,6 @@ int main(int ac, char **av) id_t pgid; id_t id1, id2, id3; siginfo_t infop; - int i = 0; int lc; char *msg; @@ -131,14 +91,14 @@ int main(int ac, char **av) TEST(waitid(P_ALL, 0, &infop, WNOHANG)); if (TEST_RETURN == -1) - tst_resm(TPASS, - "Success1 ... -1 is returned. error is %d.", - TEST_ERRNO); + 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 */ + /* option == WEXITED | WCONTINUED | WSTOPPED | + * WNOHANG | WNOWAIT */ TEST(id1 = fork()); if (TEST_RETURN == 0) { @@ -170,9 +130,8 @@ int main(int ac, char **av) 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); + tst_resm(TPASS, "Success 2 ...0 is returned.." + " error is %d.", TEST_ERRNO); else { tst_resm(TFAIL | TTERRNO, "%s Failed 2", TCID); tst_exit(); @@ -184,8 +143,8 @@ int main(int ac, char **av) 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", + tst_resm(TINFO, "si_pid = %d ; si_code = %d ;" + " si_status = %d", infop.si_pid, infop.si_code, infop.si_status); } else { @@ -197,28 +156,29 @@ int main(int ac, char **av) TEST(kill(id2, SIGSTOP)); - TEST(i = - waitid(P_PID, id2, &infop, WSTOPPED | WNOWAIT)); + TEST(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(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); + "Fail4 ... %ld is returned", + TEST_RETURN); 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(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, @@ -227,17 +187,19 @@ int main(int ac, char **av) tst_exit(); } - TEST(i = waitid(P_PID, id2, &infop, WCONTINUED)); + TEST(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(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); + "Fail6 ... %ld is returned", + TEST_RETURN); tst_exit(); } -- 1.7.1 |
From: Jan S. <jst...@re...> - 2013-05-17 08:59:45
|
Previous code in main was: - using sleep for synchronization The sleep make take longer if run in overcommitted z/VM environment with considerably high steal time, which causes testcase to hang. - missing wait for last child This patch splits code from main() into separate testcases, each with its own setup/cleanup and expected outcome. Signed-off-by: Jan Stancek <jst...@re...> --- testcases/kernel/syscalls/waitid/waitid02.c | 361 +++++++++++++++++---------- 1 files changed, 230 insertions(+), 131 deletions(-) diff --git a/testcases/kernel/syscalls/waitid/waitid02.c b/testcases/kernel/syscalls/waitid/waitid02.c index e265c32..bd5a13c 100644 --- a/testcases/kernel/syscalls/waitid/waitid02.c +++ b/testcases/kernel/syscalls/waitid/waitid02.c @@ -50,31 +50,246 @@ #include "usctest.h" #include "linux_syscall_numbers.h" +struct testcase_t { + const char *msg; + idtype_t idtype; + id_t id; + pid_t child; + int options; + int exp_ret; + int exp_errno; + int pipefd[2]; + void (*setup) (struct testcase_t *); + void (*cleanup) (struct testcase_t *); +}; + +static void setup(void); +static void cleanup(void); + +static void setup2(struct testcase_t *); +static void setup3(struct testcase_t *); +static void setup4(struct testcase_t *); +static void setup5(struct testcase_t *); +static void setup6(struct testcase_t *); +static void cleanup2(struct testcase_t *); +static void cleanup5(struct testcase_t *); +static void cleanup6(struct testcase_t *); + +struct testcase_t tdat[] = { + { + .msg = "WNOHANG", + .idtype = P_ALL, + .id = 0, + .options = WNOHANG, + .exp_ret = -1, + .exp_errno = EINVAL, + }, + { + .msg = "WNOHANG | WEXITED no child", + .idtype = P_ALL, + .id = 0, + .options = WNOHANG | WEXITED, + .exp_ret = -1, + .exp_errno = ECHILD, + }, + { + .msg = "WNOHANG | WEXITED with child", + .idtype = P_ALL, + .id = 0, + .options = WNOHANG | WEXITED, + .exp_ret = 0, + .setup = setup2, + .cleanup = cleanup2 + }, + { + .msg = "P_PGID, WEXITED wait for child", + .idtype = P_PGID, + .options = WEXITED, + .exp_ret = 0, + .setup = setup3, + }, + { + .msg = "P_PID, WEXITED wait for child", + .idtype = P_PID, + .options = WEXITED, + .exp_ret = 0, + .setup = setup4, + }, + { + .msg = "P_PID, WSTOPPED | WNOWAIT", + .idtype = P_PID, + .options = WSTOPPED | WNOWAIT, + .exp_ret = 0, + .setup = setup5, + .cleanup = cleanup5 + }, + { + .msg = "P_PID, WCONTINUED", + .idtype = P_PID, + .options = WCONTINUED, + .exp_ret = 0, + .setup = setup6, + .cleanup = cleanup6 + }, + +}; + char *TCID = "waitid02"; -int testno; -int TST_TOTAL = 4; +static int TST_TOTAL = sizeof(tdat) / sizeof(tdat[0]); -static void cleanup(void) +static void makechild(struct testcase_t *t, + void (*childfn)(struct testcase_t *)) { - TEST_CLEANUP; - tst_rmdir(); + t->child = fork(); + switch (t->child) { + case -1: + tst_brkm(TBROK | TERRNO, cleanup, "fork"); + break; + case 0: + childfn(t); + exit(0); + } +} - tst_exit(); +static void wait4child(pid_t pid) +{ + int status; + if (waitpid(pid, &status, 0) == -1) + tst_brkm(TBROK | TERRNO, cleanup, "waitpid"); + if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) + tst_resm(TFAIL, "child returns %d", status); +} + +static void dummy_child(struct testcase_t *t) +{ +} + +static void waiting_child(struct testcase_t *t) +{ + int dummy; + read(t->pipefd[0], &dummy, 1); +} + +static void stopped_child(struct testcase_t *t) +{ + int dummy; + kill(getpid(), SIGSTOP); + read(t->pipefd[0], &dummy, 1); +} + +static void setup2(struct testcase_t *t) +{ + if (pipe(t->pipefd) == -1) + tst_brkm(TBROK|TERRNO, cleanup, "pipe"); + makechild(t, waiting_child); +} + +static void cleanup2(struct testcase_t *t) +{ + write(t->pipefd[1], "", 1); + wait4child(t->child); + close(t->pipefd[0]); + close(t->pipefd[1]); +} + +static void setup3(struct testcase_t *t) +{ + t->id = getpgid(0); + makechild(t, dummy_child); +} + +static void setup4(struct testcase_t *t) +{ + makechild(t, dummy_child); + t->id = t->child; +} + +static void setup5(struct testcase_t *t) +{ + if (pipe(t->pipefd) == -1) + tst_brkm(TBROK|TERRNO, cleanup, "pipe"); + makechild(t, stopped_child); + t->id = t->child; +} + +static void cleanup5(struct testcase_t *t) +{ + kill(t->child, SIGCONT); + write(t->pipefd[1], "", 1); + wait4child(t->child); + close(t->pipefd[0]); + close(t->pipefd[1]); +} + +static void setup6(struct testcase_t *t) +{ + siginfo_t infop; + if (pipe(t->pipefd) == -1) + tst_brkm(TBROK|TERRNO, cleanup, "pipe"); + makechild(t, stopped_child); + t->id = t->child; + if (waitid(P_PID, t->child, &infop, WSTOPPED) != 0) + tst_brkm(TBROK | TERRNO, cleanup, "waitpid setup6"); + kill(t->child, SIGCONT); +} + +static void cleanup6(struct testcase_t *t) +{ + write(t->pipefd[1], "", 1); + wait4child(t->child); + close(t->pipefd[0]); + close(t->pipefd[1]); } static void setup(void) { TEST_PAUSE; - tst_tmpdir(); } -int main(int ac, char **av) +static void cleanup(void) +{ + TEST_CLEANUP; + tst_exit(); +} + +static void test_waitid(struct testcase_t *t) { - id_t pgid; - id_t id1, id2, id3; siginfo_t infop; - int lc; + if (t->setup) + t->setup(t); + + tst_resm(TINFO, "%s", t->msg); + tst_resm(TINFO, "(%d) waitid(%d, %d, %p, %d)", getpid(), t->idtype, + t->id, &infop, t->options); + memset(&infop, 0, sizeof(infop)); + + TEST(waitid(t->idtype, t->id, &infop, t->options)); + if (TEST_RETURN == t->exp_ret) { + if (TEST_RETURN == -1) { + if (TEST_ERRNO == t->exp_errno) + tst_resm(TPASS, "exp_errno=%d", t->exp_errno); + else + tst_resm(TFAIL|TTERRNO, "exp_errno=%d", + t->exp_errno); + } else { + tst_resm(TPASS, "ret: %d", t->exp_ret); + } + } else { + tst_resm(TFAIL|TTERRNO, "ret=%ld expected=%d", + TEST_RETURN, t->exp_ret); + } + tst_resm(TINFO, "si_pid = %d ; si_code = %d ; si_status = %d", + infop.si_pid, infop.si_code, + infop.si_status); + + if (t->cleanup) + t->cleanup(t); +} + +int main(int ac, char **av) +{ + int lc, testno; char *msg; msg = parse_opts(ac, av, NULL, NULL); @@ -84,127 +299,11 @@ int main(int ac, char **av) } 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(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 ... %ld is returned", - TEST_RETURN); - 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(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 ... %ld is returned", - TEST_RETURN); - tst_exit(); - } - - sleep(3); - } + /* setup alarm for unlikely event that test blocks */ + alarm(5); + for (testno = 0; testno < TST_TOTAL; testno++) + test_waitid(&tdat[testno]); } cleanup(); tst_exit(); -- 1.7.1 |
From: Wanlong G. <gao...@cn...> - 2013-05-17 10:00:44
|
On 05/17/2013 04:59 PM, Jan Stancek wrote: > Previous code in main was: > - using sleep for synchronization > The sleep make take longer if run in overcommitted > z/VM environment with considerably high steal time, which > causes testcase to hang. > - missing wait for last child > > This patch splits code from main() into separate testcases, > each with its own setup/cleanup and expected outcome. > > Signed-off-by: Jan Stancek <jst...@re...> Acked-by: Wanlong Gao <gao...@cn...> > --- > testcases/kernel/syscalls/waitid/waitid02.c | 361 +++++++++++++++++---------- > 1 files changed, 230 insertions(+), 131 deletions(-) > > diff --git a/testcases/kernel/syscalls/waitid/waitid02.c b/testcases/kernel/syscalls/waitid/waitid02.c > index e265c32..bd5a13c 100644 > --- a/testcases/kernel/syscalls/waitid/waitid02.c > +++ b/testcases/kernel/syscalls/waitid/waitid02.c > @@ -50,31 +50,246 @@ > #include "usctest.h" > #include "linux_syscall_numbers.h" > > +struct testcase_t { > + const char *msg; > + idtype_t idtype; > + id_t id; > + pid_t child; > + int options; > + int exp_ret; > + int exp_errno; > + int pipefd[2]; > + void (*setup) (struct testcase_t *); > + void (*cleanup) (struct testcase_t *); > +}; > + > +static void setup(void); > +static void cleanup(void); > + > +static void setup2(struct testcase_t *); > +static void setup3(struct testcase_t *); > +static void setup4(struct testcase_t *); > +static void setup5(struct testcase_t *); > +static void setup6(struct testcase_t *); > +static void cleanup2(struct testcase_t *); > +static void cleanup5(struct testcase_t *); > +static void cleanup6(struct testcase_t *); > + > +struct testcase_t tdat[] = { > + { > + .msg = "WNOHANG", > + .idtype = P_ALL, > + .id = 0, > + .options = WNOHANG, > + .exp_ret = -1, > + .exp_errno = EINVAL, > + }, > + { > + .msg = "WNOHANG | WEXITED no child", > + .idtype = P_ALL, > + .id = 0, > + .options = WNOHANG | WEXITED, > + .exp_ret = -1, > + .exp_errno = ECHILD, > + }, > + { > + .msg = "WNOHANG | WEXITED with child", > + .idtype = P_ALL, > + .id = 0, > + .options = WNOHANG | WEXITED, > + .exp_ret = 0, > + .setup = setup2, > + .cleanup = cleanup2 > + }, > + { > + .msg = "P_PGID, WEXITED wait for child", > + .idtype = P_PGID, > + .options = WEXITED, > + .exp_ret = 0, > + .setup = setup3, > + }, > + { > + .msg = "P_PID, WEXITED wait for child", > + .idtype = P_PID, > + .options = WEXITED, > + .exp_ret = 0, > + .setup = setup4, > + }, > + { > + .msg = "P_PID, WSTOPPED | WNOWAIT", > + .idtype = P_PID, > + .options = WSTOPPED | WNOWAIT, > + .exp_ret = 0, > + .setup = setup5, > + .cleanup = cleanup5 > + }, > + { > + .msg = "P_PID, WCONTINUED", > + .idtype = P_PID, > + .options = WCONTINUED, > + .exp_ret = 0, > + .setup = setup6, > + .cleanup = cleanup6 > + }, > + > +}; > + > char *TCID = "waitid02"; > -int testno; > -int TST_TOTAL = 4; > +static int TST_TOTAL = sizeof(tdat) / sizeof(tdat[0]); > > -static void cleanup(void) > +static void makechild(struct testcase_t *t, > + void (*childfn)(struct testcase_t *)) > { > - TEST_CLEANUP; > - tst_rmdir(); > + t->child = fork(); > + switch (t->child) { > + case -1: > + tst_brkm(TBROK | TERRNO, cleanup, "fork"); > + break; > + case 0: > + childfn(t); > + exit(0); > + } > +} > > - tst_exit(); > +static void wait4child(pid_t pid) > +{ > + int status; > + if (waitpid(pid, &status, 0) == -1) > + tst_brkm(TBROK | TERRNO, cleanup, "waitpid"); > + if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) > + tst_resm(TFAIL, "child returns %d", status); > +} > + > +static void dummy_child(struct testcase_t *t) > +{ > +} > + > +static void waiting_child(struct testcase_t *t) > +{ > + int dummy; > + read(t->pipefd[0], &dummy, 1); > +} > + > +static void stopped_child(struct testcase_t *t) > +{ > + int dummy; > + kill(getpid(), SIGSTOP); > + read(t->pipefd[0], &dummy, 1); > +} > + > +static void setup2(struct testcase_t *t) > +{ > + if (pipe(t->pipefd) == -1) > + tst_brkm(TBROK|TERRNO, cleanup, "pipe"); > + makechild(t, waiting_child); > +} > + > +static void cleanup2(struct testcase_t *t) > +{ > + write(t->pipefd[1], "", 1); > + wait4child(t->child); > + close(t->pipefd[0]); > + close(t->pipefd[1]); > +} > + > +static void setup3(struct testcase_t *t) > +{ > + t->id = getpgid(0); > + makechild(t, dummy_child); > +} > + > +static void setup4(struct testcase_t *t) > +{ > + makechild(t, dummy_child); > + t->id = t->child; > +} > + > +static void setup5(struct testcase_t *t) > +{ > + if (pipe(t->pipefd) == -1) > + tst_brkm(TBROK|TERRNO, cleanup, "pipe"); > + makechild(t, stopped_child); > + t->id = t->child; > +} > + > +static void cleanup5(struct testcase_t *t) > +{ > + kill(t->child, SIGCONT); > + write(t->pipefd[1], "", 1); > + wait4child(t->child); > + close(t->pipefd[0]); > + close(t->pipefd[1]); > +} > + > +static void setup6(struct testcase_t *t) > +{ > + siginfo_t infop; > + if (pipe(t->pipefd) == -1) > + tst_brkm(TBROK|TERRNO, cleanup, "pipe"); > + makechild(t, stopped_child); > + t->id = t->child; > + if (waitid(P_PID, t->child, &infop, WSTOPPED) != 0) > + tst_brkm(TBROK | TERRNO, cleanup, "waitpid setup6"); > + kill(t->child, SIGCONT); > +} > + > +static void cleanup6(struct testcase_t *t) > +{ > + write(t->pipefd[1], "", 1); > + wait4child(t->child); > + close(t->pipefd[0]); > + close(t->pipefd[1]); > } > > static void setup(void) > { > TEST_PAUSE; > - tst_tmpdir(); > } > > -int main(int ac, char **av) > +static void cleanup(void) > +{ > + TEST_CLEANUP; > + tst_exit(); > +} > + > +static void test_waitid(struct testcase_t *t) > { > - id_t pgid; > - id_t id1, id2, id3; > siginfo_t infop; > > - int lc; > + if (t->setup) > + t->setup(t); > + > + tst_resm(TINFO, "%s", t->msg); > + tst_resm(TINFO, "(%d) waitid(%d, %d, %p, %d)", getpid(), t->idtype, > + t->id, &infop, t->options); > + memset(&infop, 0, sizeof(infop)); > + > + TEST(waitid(t->idtype, t->id, &infop, t->options)); > + if (TEST_RETURN == t->exp_ret) { > + if (TEST_RETURN == -1) { > + if (TEST_ERRNO == t->exp_errno) > + tst_resm(TPASS, "exp_errno=%d", t->exp_errno); > + else > + tst_resm(TFAIL|TTERRNO, "exp_errno=%d", > + t->exp_errno); > + } else { > + tst_resm(TPASS, "ret: %d", t->exp_ret); > + } > + } else { > + tst_resm(TFAIL|TTERRNO, "ret=%ld expected=%d", > + TEST_RETURN, t->exp_ret); > + } > + tst_resm(TINFO, "si_pid = %d ; si_code = %d ; si_status = %d", > + infop.si_pid, infop.si_code, > + infop.si_status); > + > + if (t->cleanup) > + t->cleanup(t); > +} > + > +int main(int ac, char **av) > +{ > + int lc, testno; > char *msg; > > msg = parse_opts(ac, av, NULL, NULL); > @@ -84,127 +299,11 @@ int main(int ac, char **av) > } > > 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(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 ... %ld is returned", > - TEST_RETURN); > - 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(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 ... %ld is returned", > - TEST_RETURN); > - tst_exit(); > - } > - > - sleep(3); > - } > + /* setup alarm for unlikely event that test blocks */ > + alarm(5); > + for (testno = 0; testno < TST_TOTAL; testno++) > + test_waitid(&tdat[testno]); > } > cleanup(); > tst_exit(); > |
From: Jan S. <jst...@re...> - 2013-05-21 07:15:52
|
Previous code in main was: - using sleep for synchronization The sleep make take longer if run in overcommitted z/VM environment with considerably high steal time, which causes testcase to hang. - missing wait for last child This patch splits code from main() into separate testcases, each with its own setup/cleanup and expected outcome. Signed-off-by: Jan Stancek <jst...@re...> --- testcases/kernel/syscalls/waitid/waitid02.c | 348 +++++++++++++++++---------- 1 files changed, 218 insertions(+), 130 deletions(-) diff --git a/testcases/kernel/syscalls/waitid/waitid02.c b/testcases/kernel/syscalls/waitid/waitid02.c index e265c32..389845b 100644 --- a/testcases/kernel/syscalls/waitid/waitid02.c +++ b/testcases/kernel/syscalls/waitid/waitid02.c @@ -50,31 +50,235 @@ #include "usctest.h" #include "linux_syscall_numbers.h" +struct testcase_t { + const char *msg; + idtype_t idtype; + id_t id; + pid_t child; + int options; + int exp_ret; + int exp_errno; + void (*setup) (struct testcase_t *); + void (*cleanup) (struct testcase_t *); +}; + +static void setup(void); +static void cleanup(void); + +static void setup2(struct testcase_t *); +static void setup3(struct testcase_t *); +static void setup4(struct testcase_t *); +static void setup5(struct testcase_t *); +static void setup6(struct testcase_t *); +static void cleanup2(struct testcase_t *); +static void cleanup5(struct testcase_t *); +static void cleanup6(struct testcase_t *); + +struct testcase_t tdat[] = { + { + .msg = "WNOHANG", + .idtype = P_ALL, + .id = 0, + .options = WNOHANG, + .exp_ret = -1, + .exp_errno = EINVAL, + }, + { + .msg = "WNOHANG | WEXITED no child", + .idtype = P_ALL, + .id = 0, + .options = WNOHANG | WEXITED, + .exp_ret = -1, + .exp_errno = ECHILD, + }, + { + .msg = "WNOHANG | WEXITED with child", + .idtype = P_ALL, + .id = 0, + .options = WNOHANG | WEXITED, + .exp_ret = 0, + .setup = setup2, + .cleanup = cleanup2 + }, + { + .msg = "P_PGID, WEXITED wait for child", + .idtype = P_PGID, + .options = WEXITED, + .exp_ret = 0, + .setup = setup3, + }, + { + .msg = "P_PID, WEXITED wait for child", + .idtype = P_PID, + .options = WEXITED, + .exp_ret = 0, + .setup = setup4, + }, + { + .msg = "P_PID, WSTOPPED | WNOWAIT", + .idtype = P_PID, + .options = WSTOPPED | WNOWAIT, + .exp_ret = 0, + .setup = setup5, + .cleanup = cleanup5 + }, + { + .msg = "P_PID, WCONTINUED", + .idtype = P_PID, + .options = WCONTINUED, + .exp_ret = 0, + .setup = setup6, + .cleanup = cleanup6 + }, + +}; + char *TCID = "waitid02"; -int testno; -int TST_TOTAL = 4; +static int TST_TOTAL = sizeof(tdat) / sizeof(tdat[0]); +static struct tst_checkpoint checkpoint; -static void cleanup(void) +static void makechild(struct testcase_t *t, + void (*childfn)(struct testcase_t *)) { - TEST_CLEANUP; - tst_rmdir(); + t->child = fork(); + switch (t->child) { + case -1: + tst_brkm(TBROK | TERRNO, cleanup, "fork"); + break; + case 0: + childfn(t); + exit(0); + } +} - tst_exit(); +static void wait4child(pid_t pid) +{ + int status; + if (waitpid(pid, &status, 0) == -1) + tst_brkm(TBROK | TERRNO, cleanup, "waitpid"); + if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) + tst_resm(TFAIL, "child returns %d", status); +} + +static void dummy_child(struct testcase_t *t) +{ +} + +static void waiting_child(struct testcase_t *t) +{ + TST_CHECKPOINT_CHILD_WAIT(&checkpoint); +} + +static void stopped_child(struct testcase_t *t) +{ + kill(getpid(), SIGSTOP); + TST_CHECKPOINT_CHILD_WAIT(&checkpoint); +} + +static void setup2(struct testcase_t *t) +{ + makechild(t, waiting_child); +} + +static void cleanup2(struct testcase_t *t) +{ + TST_CHECKPOINT_SIGNAL_CHILD(cleanup, &checkpoint); + wait4child(t->child); +} + +static void setup3(struct testcase_t *t) +{ + t->id = getpgid(0); + makechild(t, dummy_child); +} + +static void setup4(struct testcase_t *t) +{ + makechild(t, dummy_child); + t->id = t->child; +} + +static void setup5(struct testcase_t *t) +{ + makechild(t, stopped_child); + t->id = t->child; +} + +static void cleanup5(struct testcase_t *t) +{ + kill(t->child, SIGCONT); + TST_CHECKPOINT_SIGNAL_CHILD(cleanup, &checkpoint); + wait4child(t->child); +} + +static void setup6(struct testcase_t *t) +{ + siginfo_t infop; + makechild(t, stopped_child); + t->id = t->child; + if (waitid(P_PID, t->child, &infop, WSTOPPED) != 0) + tst_brkm(TBROK | TERRNO, cleanup, "waitpid setup6"); + kill(t->child, SIGCONT); +} + +static void cleanup6(struct testcase_t *t) +{ + TST_CHECKPOINT_SIGNAL_CHILD(cleanup, &checkpoint); + wait4child(t->child); } static void setup(void) { TEST_PAUSE; tst_tmpdir(); + TST_CHECKPOINT_INIT(&checkpoint); } -int main(int ac, char **av) +static void cleanup(void) +{ + TEST_CLEANUP; + tst_rmdir(); + tst_exit(); +} + +static void test_waitid(struct testcase_t *t) { - id_t pgid; - id_t id1, id2, id3; siginfo_t infop; - int lc; + if (t->setup) + t->setup(t); + + tst_resm(TINFO, "%s", t->msg); + tst_resm(TINFO, "(%d) waitid(%d, %d, %p, %d)", getpid(), t->idtype, + t->id, &infop, t->options); + memset(&infop, 0, sizeof(infop)); + + TEST(waitid(t->idtype, t->id, &infop, t->options)); + if (TEST_RETURN == t->exp_ret) { + if (TEST_RETURN == -1) { + if (TEST_ERRNO == t->exp_errno) + tst_resm(TPASS, "exp_errno=%d", t->exp_errno); + else + tst_resm(TFAIL|TTERRNO, "exp_errno=%d", + t->exp_errno); + } else { + tst_resm(TPASS, "ret: %d", t->exp_ret); + } + } else { + tst_resm(TFAIL|TTERRNO, "ret=%ld expected=%d", + TEST_RETURN, t->exp_ret); + } + tst_resm(TINFO, "si_pid = %d ; si_code = %d ; si_status = %d", + infop.si_pid, infop.si_code, + infop.si_status); + + if (t->cleanup) + t->cleanup(t); +} + +int main(int ac, char **av) +{ + int lc, testno; char *msg; msg = parse_opts(ac, av, NULL, NULL); @@ -84,127 +288,11 @@ int main(int ac, char **av) } 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(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 ... %ld is returned", - TEST_RETURN); - 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(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 ... %ld is returned", - TEST_RETURN); - tst_exit(); - } - - sleep(3); - } + /* setup alarm for unlikely event that test blocks */ + alarm(5); + for (testno = 0; testno < TST_TOTAL; testno++) + test_waitid(&tdat[testno]); } cleanup(); tst_exit(); -- 1.7.1 |
From: Jan S. <jst...@re...> - 2013-05-23 08:25:06
|
Previous code in main was: - using sleep for synchronization The sleep make take longer if run in overcommitted z/VM environment with considerably high steal time, which causes testcase to hang. - missing wait for last child This patch splits code from main() into separate testcases, each with its own setup/cleanup and expected outcome. Signed-off-by: Jan Stancek <jst...@re...> --- testcases/kernel/syscalls/waitid/waitid02.c | 346 +++++++++++++++++---------- 1 files changed, 216 insertions(+), 130 deletions(-) diff --git a/testcases/kernel/syscalls/waitid/waitid02.c b/testcases/kernel/syscalls/waitid/waitid02.c index e265c32..c843f30 100644 --- a/testcases/kernel/syscalls/waitid/waitid02.c +++ b/testcases/kernel/syscalls/waitid/waitid02.c @@ -50,31 +50,235 @@ #include "usctest.h" #include "linux_syscall_numbers.h" +struct testcase_t { + const char *msg; + idtype_t idtype; + id_t id; + pid_t child; + int options; + int exp_ret; + int exp_errno; + void (*setup) (struct testcase_t *); + void (*cleanup) (struct testcase_t *); +}; + +static void setup(void); +static void cleanup(void); + +static void setup2(struct testcase_t *); +static void setup3(struct testcase_t *); +static void setup4(struct testcase_t *); +static void setup5(struct testcase_t *); +static void setup6(struct testcase_t *); +static void cleanup2(struct testcase_t *); +static void cleanup5(struct testcase_t *); +static void cleanup6(struct testcase_t *); + +struct testcase_t tdat[] = { + { + .msg = "WNOHANG", + .idtype = P_ALL, + .id = 0, + .options = WNOHANG, + .exp_ret = -1, + .exp_errno = EINVAL, + }, + { + .msg = "WNOHANG | WEXITED no child", + .idtype = P_ALL, + .id = 0, + .options = WNOHANG | WEXITED, + .exp_ret = -1, + .exp_errno = ECHILD, + }, + { + .msg = "WNOHANG | WEXITED with child", + .idtype = P_ALL, + .id = 0, + .options = WNOHANG | WEXITED, + .exp_ret = 0, + .setup = setup2, + .cleanup = cleanup2 + }, + { + .msg = "P_PGID, WEXITED wait for child", + .idtype = P_PGID, + .options = WEXITED, + .exp_ret = 0, + .setup = setup3, + }, + { + .msg = "P_PID, WEXITED wait for child", + .idtype = P_PID, + .options = WEXITED, + .exp_ret = 0, + .setup = setup4, + }, + { + .msg = "P_PID, WSTOPPED | WNOWAIT", + .idtype = P_PID, + .options = WSTOPPED | WNOWAIT, + .exp_ret = 0, + .setup = setup5, + .cleanup = cleanup5 + }, + { + .msg = "P_PID, WCONTINUED", + .idtype = P_PID, + .options = WCONTINUED, + .exp_ret = 0, + .setup = setup6, + .cleanup = cleanup6 + }, + +}; + char *TCID = "waitid02"; -int testno; -int TST_TOTAL = 4; +static int TST_TOTAL = ARRAY_SIZE(tdat); +static struct tst_checkpoint checkpoint; -static void cleanup(void) +static void makechild(struct testcase_t *t, + void (*childfn)(struct testcase_t *)) { - TEST_CLEANUP; - tst_rmdir(); + t->child = fork(); + switch (t->child) { + case -1: + tst_brkm(TBROK | TERRNO, cleanup, "fork"); + break; + case 0: + childfn(t); + exit(0); + } +} - tst_exit(); +static void wait4child(pid_t pid) +{ + int status; + if (waitpid(pid, &status, 0) == -1) + tst_brkm(TBROK | TERRNO, cleanup, "waitpid"); + if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) + tst_resm(TFAIL, "child returns %d", status); +} + +static void dummy_child(struct testcase_t *t) +{ +} + +static void waiting_child(struct testcase_t *t) +{ + TST_CHECKPOINT_CHILD_WAIT(&checkpoint); +} + +static void stopped_child(struct testcase_t *t) +{ + kill(getpid(), SIGSTOP); + TST_CHECKPOINT_CHILD_WAIT(&checkpoint); +} + +static void setup2(struct testcase_t *t) +{ + makechild(t, waiting_child); +} + +static void cleanup2(struct testcase_t *t) +{ + TST_CHECKPOINT_SIGNAL_CHILD(cleanup, &checkpoint); + wait4child(t->child); +} + +static void setup3(struct testcase_t *t) +{ + t->id = getpgid(0); + makechild(t, dummy_child); +} + +static void setup4(struct testcase_t *t) +{ + makechild(t, dummy_child); + t->id = t->child; +} + +static void setup5(struct testcase_t *t) +{ + makechild(t, stopped_child); + t->id = t->child; +} + +static void cleanup5(struct testcase_t *t) +{ + kill(t->child, SIGCONT); + TST_CHECKPOINT_SIGNAL_CHILD(cleanup, &checkpoint); + wait4child(t->child); +} + +static void setup6(struct testcase_t *t) +{ + siginfo_t infop; + makechild(t, stopped_child); + t->id = t->child; + if (waitid(P_PID, t->child, &infop, WSTOPPED) != 0) + tst_brkm(TBROK | TERRNO, cleanup, "waitpid setup6"); + kill(t->child, SIGCONT); +} + +static void cleanup6(struct testcase_t *t) +{ + TST_CHECKPOINT_SIGNAL_CHILD(cleanup, &checkpoint); + wait4child(t->child); } static void setup(void) { TEST_PAUSE; tst_tmpdir(); + TST_CHECKPOINT_INIT(&checkpoint); } -int main(int ac, char **av) +static void cleanup(void) +{ + TEST_CLEANUP; + tst_rmdir(); + tst_exit(); +} + +static void test_waitid(struct testcase_t *t) { - id_t pgid; - id_t id1, id2, id3; siginfo_t infop; - int lc; + if (t->setup) + t->setup(t); + + tst_resm(TINFO, "%s", t->msg); + tst_resm(TINFO, "(%d) waitid(%d, %d, %p, %d)", getpid(), t->idtype, + t->id, &infop, t->options); + memset(&infop, 0, sizeof(infop)); + + TEST(waitid(t->idtype, t->id, &infop, t->options)); + if (TEST_RETURN == t->exp_ret) { + if (TEST_RETURN == -1) { + if (TEST_ERRNO == t->exp_errno) + tst_resm(TPASS, "exp_errno=%d", t->exp_errno); + else + tst_resm(TFAIL|TTERRNO, "exp_errno=%d", + t->exp_errno); + } else { + tst_resm(TPASS, "ret: %d", t->exp_ret); + } + } else { + tst_resm(TFAIL|TTERRNO, "ret=%ld expected=%d", + TEST_RETURN, t->exp_ret); + } + tst_resm(TINFO, "si_pid = %d ; si_code = %d ; si_status = %d", + infop.si_pid, infop.si_code, + infop.si_status); + + if (t->cleanup) + t->cleanup(t); +} + +int main(int ac, char **av) +{ + int lc, testno; char *msg; msg = parse_opts(ac, av, NULL, NULL); @@ -84,127 +288,9 @@ int main(int ac, char **av) } 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(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 ... %ld is returned", - TEST_RETURN); - 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(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 ... %ld is returned", - TEST_RETURN); - tst_exit(); - } - - sleep(3); - } + for (testno = 0; testno < TST_TOTAL; testno++) + test_waitid(&tdat[testno]); } cleanup(); tst_exit(); -- 1.7.1 |
From: <ch...@su...> - 2013-05-27 16:19:24
|
Hi! > +static void dummy_child(struct testcase_t *t) > +{ > +} > + > +static void waiting_child(struct testcase_t *t) > +{ > + TST_CHECKPOINT_CHILD_WAIT(&checkpoint); > +} > + > +static void stopped_child(struct testcase_t *t) > +{ > + kill(getpid(), SIGSTOP); > + TST_CHECKPOINT_CHILD_WAIT(&checkpoint); > +} Looks like none of the childs is using the parameter after the change to checkpoint interface. We may remove it then. The rest if fine. (Acked-By: Cyril Hrubis <ch...@su...>) -- Cyril Hrubis ch...@su... |
From: Jan S. <jst...@re...> - 2013-05-27 17:02:35
|
Previous code in main was: - using sleep for synchronization The sleep make take longer if run in overcommitted z/VM environment with considerably high steal time, which causes testcase to hang. - missing wait for last child This patch splits code from main() into separate testcases, each with its own setup/cleanup and expected outcome. Signed-off-by: Jan Stancek <jst...@re...> --- testcases/kernel/syscalls/waitid/waitid02.c | 345 +++++++++++++++++---------- 1 files changed, 215 insertions(+), 130 deletions(-) diff --git a/testcases/kernel/syscalls/waitid/waitid02.c b/testcases/kernel/syscalls/waitid/waitid02.c index e265c32..d4806b4 100644 --- a/testcases/kernel/syscalls/waitid/waitid02.c +++ b/testcases/kernel/syscalls/waitid/waitid02.c @@ -50,31 +50,234 @@ #include "usctest.h" #include "linux_syscall_numbers.h" +struct testcase_t { + const char *msg; + idtype_t idtype; + id_t id; + pid_t child; + int options; + int exp_ret; + int exp_errno; + void (*setup) (struct testcase_t *); + void (*cleanup) (struct testcase_t *); +}; + +static void setup(void); +static void cleanup(void); + +static void setup2(struct testcase_t *); +static void setup3(struct testcase_t *); +static void setup4(struct testcase_t *); +static void setup5(struct testcase_t *); +static void setup6(struct testcase_t *); +static void cleanup2(struct testcase_t *); +static void cleanup5(struct testcase_t *); +static void cleanup6(struct testcase_t *); + +struct testcase_t tdat[] = { + { + .msg = "WNOHANG", + .idtype = P_ALL, + .id = 0, + .options = WNOHANG, + .exp_ret = -1, + .exp_errno = EINVAL, + }, + { + .msg = "WNOHANG | WEXITED no child", + .idtype = P_ALL, + .id = 0, + .options = WNOHANG | WEXITED, + .exp_ret = -1, + .exp_errno = ECHILD, + }, + { + .msg = "WNOHANG | WEXITED with child", + .idtype = P_ALL, + .id = 0, + .options = WNOHANG | WEXITED, + .exp_ret = 0, + .setup = setup2, + .cleanup = cleanup2 + }, + { + .msg = "P_PGID, WEXITED wait for child", + .idtype = P_PGID, + .options = WEXITED, + .exp_ret = 0, + .setup = setup3, + }, + { + .msg = "P_PID, WEXITED wait for child", + .idtype = P_PID, + .options = WEXITED, + .exp_ret = 0, + .setup = setup4, + }, + { + .msg = "P_PID, WSTOPPED | WNOWAIT", + .idtype = P_PID, + .options = WSTOPPED | WNOWAIT, + .exp_ret = 0, + .setup = setup5, + .cleanup = cleanup5 + }, + { + .msg = "P_PID, WCONTINUED", + .idtype = P_PID, + .options = WCONTINUED, + .exp_ret = 0, + .setup = setup6, + .cleanup = cleanup6 + }, + +}; + char *TCID = "waitid02"; -int testno; -int TST_TOTAL = 4; +static int TST_TOTAL = ARRAY_SIZE(tdat); +static struct tst_checkpoint checkpoint; -static void cleanup(void) +static void makechild(struct testcase_t *t, void (*childfn)(void)) { - TEST_CLEANUP; - tst_rmdir(); + t->child = fork(); + switch (t->child) { + case -1: + tst_brkm(TBROK | TERRNO, cleanup, "fork"); + break; + case 0: + childfn(); + exit(0); + } +} - tst_exit(); +static void wait4child(pid_t pid) +{ + int status; + if (waitpid(pid, &status, 0) == -1) + tst_brkm(TBROK | TERRNO, cleanup, "waitpid"); + if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) + tst_resm(TFAIL, "child returns %d", status); +} + +static void dummy_child(void) +{ +} + +static void waiting_child(void) +{ + TST_CHECKPOINT_CHILD_WAIT(&checkpoint); +} + +static void stopped_child(void) +{ + kill(getpid(), SIGSTOP); + TST_CHECKPOINT_CHILD_WAIT(&checkpoint); +} + +static void setup2(struct testcase_t *t) +{ + makechild(t, waiting_child); +} + +static void cleanup2(struct testcase_t *t) +{ + TST_CHECKPOINT_SIGNAL_CHILD(cleanup, &checkpoint); + wait4child(t->child); +} + +static void setup3(struct testcase_t *t) +{ + t->id = getpgid(0); + makechild(t, dummy_child); +} + +static void setup4(struct testcase_t *t) +{ + makechild(t, dummy_child); + t->id = t->child; +} + +static void setup5(struct testcase_t *t) +{ + makechild(t, stopped_child); + t->id = t->child; +} + +static void cleanup5(struct testcase_t *t) +{ + kill(t->child, SIGCONT); + TST_CHECKPOINT_SIGNAL_CHILD(cleanup, &checkpoint); + wait4child(t->child); +} + +static void setup6(struct testcase_t *t) +{ + siginfo_t infop; + makechild(t, stopped_child); + t->id = t->child; + if (waitid(P_PID, t->child, &infop, WSTOPPED) != 0) + tst_brkm(TBROK | TERRNO, cleanup, "waitpid setup6"); + kill(t->child, SIGCONT); +} + +static void cleanup6(struct testcase_t *t) +{ + TST_CHECKPOINT_SIGNAL_CHILD(cleanup, &checkpoint); + wait4child(t->child); } static void setup(void) { TEST_PAUSE; tst_tmpdir(); + TST_CHECKPOINT_INIT(&checkpoint); } -int main(int ac, char **av) +static void cleanup(void) +{ + TEST_CLEANUP; + tst_rmdir(); + tst_exit(); +} + +static void test_waitid(struct testcase_t *t) { - id_t pgid; - id_t id1, id2, id3; siginfo_t infop; - int lc; + if (t->setup) + t->setup(t); + + tst_resm(TINFO, "%s", t->msg); + tst_resm(TINFO, "(%d) waitid(%d, %d, %p, %d)", getpid(), t->idtype, + t->id, &infop, t->options); + memset(&infop, 0, sizeof(infop)); + + TEST(waitid(t->idtype, t->id, &infop, t->options)); + if (TEST_RETURN == t->exp_ret) { + if (TEST_RETURN == -1) { + if (TEST_ERRNO == t->exp_errno) + tst_resm(TPASS, "exp_errno=%d", t->exp_errno); + else + tst_resm(TFAIL|TTERRNO, "exp_errno=%d", + t->exp_errno); + } else { + tst_resm(TPASS, "ret: %d", t->exp_ret); + } + } else { + tst_resm(TFAIL|TTERRNO, "ret=%ld expected=%d", + TEST_RETURN, t->exp_ret); + } + tst_resm(TINFO, "si_pid = %d ; si_code = %d ; si_status = %d", + infop.si_pid, infop.si_code, + infop.si_status); + + if (t->cleanup) + t->cleanup(t); +} + +int main(int ac, char **av) +{ + int lc, testno; char *msg; msg = parse_opts(ac, av, NULL, NULL); @@ -84,127 +287,9 @@ int main(int ac, char **av) } 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(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 ... %ld is returned", - TEST_RETURN); - 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(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 ... %ld is returned", - TEST_RETURN); - tst_exit(); - } - - sleep(3); - } + for (testno = 0; testno < TST_TOTAL; testno++) + test_waitid(&tdat[testno]); } cleanup(); tst_exit(); -- 1.7.1 |
From: <ch...@su...> - 2013-05-27 17:16:28
|
Hi! > Previous code in main was: > - using sleep for synchronization > The sleep make take longer if run in overcommitted > z/VM environment with considerably high steal time, which > causes testcase to hang. > - missing wait for last child > > This patch splits code from main() into separate testcases, > each with its own setup/cleanup and expected outcome. > > Signed-off-by: Jan Stancek <jst...@re...> You should have just commited this one. The change is cosmetic and the previous version was available for reviews (on the list) long enough. -- Cyril Hrubis ch...@su... |
From: Jan S. <jst...@re...> - 2013-05-28 06:48:24
|
----- Original Message ----- > From: ch...@su... > To: "Jan Stancek" <jst...@re...> > Cc: ltp...@li... > Sent: Monday, 27 May, 2013 7:17:40 PM > Subject: Re: [LTP] [PATCH v4 2/2] waitid02: split code into separate testcases > > Hi! > > Previous code in main was: > > - using sleep for synchronization > > The sleep make take longer if run in overcommitted > > z/VM environment with considerably high steal time, which > > causes testcase to hang. > > - missing wait for last child > > > > This patch splits code from main() into separate testcases, > > each with its own setup/cleanup and expected outcome. > > > > Signed-off-by: Jan Stancek <jst...@re...> > > You should have just commited this one. The change is cosmetic and the > previous version was available for reviews (on the list) long enough. OK, v4 is committed. Regards, Jan > > -- > Cyril Hrubis > ch...@su... > |
From: <ch...@su...> - 2013-05-22 15:01:24
|
Hi! > -int TST_TOTAL = 4; > +static int TST_TOTAL = sizeof(tdat) / sizeof(tdat[0]); You can use ARRAY_SIZE() macro we have. ;) > - } > + /* setup alarm for unlikely event that test blocks */ > + alarm(5); I'm slightly against adding timeouts to tests in this fashion. The correct solution for this would be making the test driver to kill the test after some timeout. Which is what I want to solve with new test execution framework (that unfortunately does not exist at the moment). I guess that we can hack around some default timeout (30 mins or something equally big) into ltp-pan.c for the time being. Which would at least assure that the testsuite will not hang forever. We can't do anything smarter without anotating long lived testcases (more than five minutes or so) with proper timeouts in the runtest files though :(. > cleanup(); > tst_exit(); The rest is fine. -- Cyril Hrubis ch...@su... |
From: Jan S. <jst...@re...> - 2013-05-22 15:19:38
|
----- Original Message ----- > From: ch...@su... > To: "Jan Stancek" <jst...@re...> > Cc: ltp...@li... > Sent: Wednesday, 22 May, 2013 5:02:34 PM > Subject: Re: [LTP] [PATCH v2 2/2] waitid02: split code into separate testcases > > Hi! > > -int TST_TOTAL = 4; > > +static int TST_TOTAL = sizeof(tdat) / sizeof(tdat[0]); > > You can use ARRAY_SIZE() macro we have. ;) Sure. > > > - } > > + /* setup alarm for unlikely event that test blocks */ > > + alarm(5); > > I'm slightly against adding timeouts to tests in this fashion. OK, I'll remove it in v3. > > The correct solution for this would be making the test driver to kill > the test after some timeout. Which is what I want to solve with new test > execution framework (that unfortunately does not exist at the moment). > > I guess that we can hack around some default timeout (30 mins or > something equally big) into ltp-pan.c for the time being. Which would at > least assure that the testsuite will not hang forever. We can't do > anything smarter without anotating long lived testcases (more than five > minutes or so) with proper timeouts in the runtest files though :(. > > > cleanup(); > > tst_exit(); > > The rest is fine. Thanks for reviewing. Regards, Jan > > -- > Cyril Hrubis > ch...@su... > |
From: Wanlong G. <gao...@cn...> - 2013-05-17 10:00:42
|
On 05/17/2013 04:59 PM, Jan Stancek wrote: > Remove useless comments, convert spaces to tabs > and fix long lines. > > Signed-off-by: Jan Stancek <jst...@re...> Acked-by: Wanlong Gao <gao...@cn...> > --- > testcases/kernel/syscalls/waitid/waitid02.c | 104 +++++++++------------------ > 1 files changed, 33 insertions(+), 71 deletions(-) > > diff --git a/testcases/kernel/syscalls/waitid/waitid02.c b/testcases/kernel/syscalls/waitid/waitid02.c > index 98bf3ea..e265c32 100644 > --- a/testcases/kernel/syscalls/waitid/waitid02.c > +++ b/testcases/kernel/syscalls/waitid/waitid02.c > @@ -11,9 +11,9 @@ > /* 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; if not, write to the Free Software */ > -/* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ > +/* 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 */ > /* */ > /******************************************************************************/ > /******************************************************************************/ > @@ -54,55 +54,16 @@ char *TCID = "waitid02"; > int testno; > int TST_TOTAL = 4; > > -/* Extern Global Functions */ > -/******************************************************************************/ > -/* */ > -/* Function: cleanup */ > -/* */ > -/* Description: Performs all one time clean up for this test on successful */ > -/* completion, premature exit or failure. Closes all temporary */ > -/* files, removes all temporary directories exits the test with */ > -/* appropriate return code by calling tst_exit() function. */ > -/* */ > -/* Input: None. */ > -/* */ > -/* Output: None. */ > -/* */ > -/* Return: On failure - Exits calling tst_exit(). Non '0' return code. */ > -/* On success - Exits calling tst_exit(). With '0' return code. */ > -/* */ > -/******************************************************************************/ > -extern void cleanup() > +static void cleanup(void) > { > - > TEST_CLEANUP; > tst_rmdir(); > > tst_exit(); > } > > -/* Local Functions */ > -/******************************************************************************/ > -/* */ > -/* Function: setup */ > -/* */ > -/* Description: Performs all one time setup for this test. This function is */ > -/* typically used to capture signals, create temporary dirs */ > -/* and temporary files that may be used in the course of this */ > -/* test. */ > -/* */ > -/* Input: None. */ > -/* */ > -/* Output: None. */ > -/* */ > -/* Return: On failure - Exits by calling cleanup(). */ > -/* On success - returns 0. */ > -/* */ > -/******************************************************************************/ > -void setup() > +static void setup(void) > { > - /* Capture signals if any */ > - /* Create temporary directories */ > TEST_PAUSE; > tst_tmpdir(); > } > @@ -112,7 +73,6 @@ int main(int ac, char **av) > id_t pgid; > id_t id1, id2, id3; > siginfo_t infop; > - int i = 0; > > int lc; > char *msg; > @@ -131,14 +91,14 @@ int main(int ac, char **av) > > TEST(waitid(P_ALL, 0, &infop, WNOHANG)); > if (TEST_RETURN == -1) > - tst_resm(TPASS, > - "Success1 ... -1 is returned. error is %d.", > - TEST_ERRNO); > + 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 */ > + /* option == WEXITED | WCONTINUED | WSTOPPED | > + * WNOHANG | WNOWAIT */ > > TEST(id1 = fork()); > if (TEST_RETURN == 0) { > @@ -170,9 +130,8 @@ int main(int ac, char **av) > > 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); > + tst_resm(TPASS, "Success 2 ...0 is returned.." > + " error is %d.", TEST_ERRNO); > else { > tst_resm(TFAIL | TTERRNO, "%s Failed 2", TCID); > tst_exit(); > @@ -184,8 +143,8 @@ int main(int ac, char **av) > 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", > + tst_resm(TINFO, "si_pid = %d ; si_code = %d ;" > + " si_status = %d", > infop.si_pid, infop.si_code, > infop.si_status); > } else { > @@ -197,28 +156,29 @@ int main(int ac, char **av) > > TEST(kill(id2, SIGSTOP)); > > - TEST(i = > - waitid(P_PID, id2, &infop, WSTOPPED | WNOWAIT)); > + TEST(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(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); > + "Fail4 ... %ld is returned", > + TEST_RETURN); > 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(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, > @@ -227,17 +187,19 @@ int main(int ac, char **av) > tst_exit(); > } > > - TEST(i = waitid(P_PID, id2, &infop, WCONTINUED)); > + TEST(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(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); > + "Fail6 ... %ld is returned", > + TEST_RETURN); > tst_exit(); > } > > |
From: <ch...@su...> - 2013-05-20 14:47:21
|
Hi! > +static void waiting_child(struct testcase_t *t) > +{ > + int dummy; > + read(t->pipefd[0], &dummy, 1); > +} > + > +static void stopped_child(struct testcase_t *t) > +{ > + int dummy; > + kill(getpid(), SIGSTOP); > + read(t->pipefd[0], &dummy, 1); > +} > + > +static void setup2(struct testcase_t *t) > +{ > + if (pipe(t->pipefd) == -1) > + tst_brkm(TBROK|TERRNO, cleanup, "pipe"); > + makechild(t, waiting_child); I wonder if it would be better to use the TST_CHECKPOINT() interface that I have written to address synchronization issues. Have you used pipes because you wanted to avoid tst_tmpdir() and the FIFO that the code uses? Unfortunately the checkpoint interface must use fifo instead of pipes to be usable for cases where the file descriptors cannot be propagated to child because it does exec() right after fork()... If that is the issue, I can rewrite the checkpoint interface in a way that would allow either pipe or fifo depending on initialization parameters. -- Cyril Hrubis ch...@su... |
From: Jan S. <jst...@re...> - 2013-05-20 15:15:32
|
----- Original Message ----- > From: ch...@su... > To: "Jan Stancek" <jst...@re...> > Cc: ltp...@li... > Sent: Monday, 20 May, 2013 4:48:27 PM > Subject: Re: [LTP] [PATCH 2/2] waitid02: split code into separate testcases > > Hi! > > +static void waiting_child(struct testcase_t *t) > > +{ > > + int dummy; > > + read(t->pipefd[0], &dummy, 1); > > +} > > + > > +static void stopped_child(struct testcase_t *t) > > +{ > > + int dummy; > > + kill(getpid(), SIGSTOP); > > + read(t->pipefd[0], &dummy, 1); > > +} > > + > > +static void setup2(struct testcase_t *t) > > +{ > > + if (pipe(t->pipefd) == -1) > > + tst_brkm(TBROK|TERRNO, cleanup, "pipe"); > > + makechild(t, waiting_child); > > I wonder if it would be better to use the TST_CHECKPOINT() interface > that I have written to address synchronization issues. I recall that we talked about limitation of single checkpoint per test and since there were 3 children it somehow got stuck in my head that I need pipes. But as I split it into separate testcases that should no longer apply. I'll look into converting it to use TST_CHECKPOINT(). Regards, Jan > > Have you used pipes because you wanted to avoid tst_tmpdir() and the > FIFO that the code uses? Unfortunately the checkpoint interface must use > fifo instead of pipes to be usable for cases where the file descriptors > cannot be propagated to child because it does exec() right after > fork()... If that is the issue, I can rewrite the checkpoint interface > in a way that would allow either pipe or fifo depending on > initialization parameters. > > -- > Cyril Hrubis > ch...@su... > |
From: <ch...@su...> - 2013-05-20 15:20:16
|
Hi! > I recall that we talked about limitation of single checkpoint per test and > since there were 3 children it somehow got stuck in my head that I need pipes. > But as I split it into separate testcases that should no longer apply. > I'll look into converting it to use TST_CHECKPOINT(). There could be one instance of the checkpoint active at the time but that is only because the TST_CHECKPOINT_INIT() does not take the FIFO name as a parameter. The rest of the code does mostly what the pipe() does but includes the timeout detection and has more strict error condition checks. If you create one checkpoint at global setup, you can reuse it in the rest of the testcases given that WAIT and SIGNAL is called exacly once for each test and test are not executed in parallel. -- Cyril Hrubis ch...@su... |
From: <ch...@su...> - 2013-05-20 15:41:11
|
Hi! > There could be one instance of the checkpoint active at the time but > that is only because the TST_CHECKPOINT_INIT() does not take the FIFO > name as a parameter. The rest of the code does mostly what the pipe() > does but includes the timeout detection and has more strict error > condition checks. > > If you create one checkpoint at global setup, you can reuse it in the > rest of the testcases given that WAIT and SIGNAL is called exacly once > for each test and test are not executed in parallel. And I forgett to add, if the interface does not work for you, feel free to propose changes (there is not much of tests that use this interface yet so it is realtively easy to modify the API and fix the few usages). -- Cyril Hrubis ch...@su... |