From: zenglg.jy <zen...@cn...> - 2013-11-14 04:07:33
|
Add new case for clone(2) with CLONE_PARENT, CLONE_CHILD_SETTID, CLONE_PARENT_SETTID, CLONE_STOPPED, CLONE_THREAD. Signed-off-by: Zeng Linggang <zen...@cn...> --- runtest/ltplite | 1 + runtest/stress.part3 | 1 + runtest/syscalls | 1 + testcases/kernel/syscalls/.gitignore | 1 + testcases/kernel/syscalls/clone/clone08.c | 192 ++++++++++++++++++++++++++++++ 5 files changed, 196 insertions(+) create mode 100644 testcases/kernel/syscalls/clone/clone08.c diff --git a/runtest/ltplite b/runtest/ltplite index f0738c7..71dbb5e 100644 --- a/runtest/ltplite +++ b/runtest/ltplite @@ -126,6 +126,7 @@ clone04 clone04 clone05 clone05 clone06 clone06 clone07 clone07 +clone08 clone08 close01 close01 close02 close02 diff --git a/runtest/stress.part3 b/runtest/stress.part3 index 951b00e..8c42e1b 100644 --- a/runtest/stress.part3 +++ b/runtest/stress.part3 @@ -67,6 +67,7 @@ clone04 clone04 clone05 clone05 clone06 clone06 clone07 clone07 +clone08 clone08 close01 close01 close02 close02 diff --git a/runtest/syscalls b/runtest/syscalls index e5a5508..33cb11c 100644 --- a/runtest/syscalls +++ b/runtest/syscalls @@ -84,6 +84,7 @@ clone04 clone04 clone05 clone05 clone06 clone06 clone07 clone07 +clone08 clone08 close01 close01 close02 close02 diff --git a/testcases/kernel/syscalls/.gitignore b/testcases/kernel/syscalls/.gitignore index 0effa6b..35dd2c5 100644 --- a/testcases/kernel/syscalls/.gitignore +++ b/testcases/kernel/syscalls/.gitignore @@ -64,6 +64,7 @@ /clone/clone05 /clone/clone06 /clone/clone07 +/clone/clone08 /close/close01 /close/close02 /close/close08 diff --git a/testcases/kernel/syscalls/clone/clone08.c b/testcases/kernel/syscalls/clone/clone08.c new file mode 100644 index 0000000..fd82274 --- /dev/null +++ b/testcases/kernel/syscalls/clone/clone08.c @@ -0,0 +1,192 @@ +/* + * Copyright (c) 2013 Fujitsu Ltd. + * Author: Zeng Linggang <zen...@cn...> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it would be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#if defined UCLINUX && !__THROW +/* workaround for libc bug */ +#define __THROW +#endif + +#include <errno.h> +#include <linux/sched.h> +#include <sys/wait.h> +#include "test.h" +#include "usctest.h" +#include "clone_platform.h" +#include "linux_syscall_numbers.h" + + +static pid_t parent_ppid; +static pid_t ptid, ctid; +static pid_t tgid; +static void *child_stack; + +static void setup(void); +static void cleanup(void); + +static int child_clone_parent(); +static int child_clone_child_settid(); +static int child_clone_parent_settid(); + +static void test_clone_parent_settid(int tid); + +#ifdef CLONE_STOPPED +static int thread_state; +static void test_clone_stopped(int tid); +static int child_clone_stopped(); +#endif + +static int notwait_flag = CLONE_PARENT; +static struct test_case { + char *name; + int flags; + void (*testfunc)(int tid); + int (*do_child)(); +} test_cases[] = { + {"CLONE_PARENT", CLONE_PARENT, NULL, child_clone_parent}, + {"CLONE_CHILD_SETTID", CLONE_CHILD_SETTID | SIGCHLD, NULL, + child_clone_child_settid}, + {"CLONE_PARENT_SETTID", CLONE_PARENT_SETTID | SIGCHLD, + test_clone_parent_settid, child_clone_parent_settid}, +#ifdef CLONE_STOPPED + {"CLONE_STOPPED", CLONE_STOPPED | SIGCHLD, test_clone_stopped, + child_clone_stopped}, +#endif +}; + +char *TCID = "clone08"; +int TST_TOTAL = ARRAY_SIZE(test_cases); + +int main(int ac, char **av) +{ + int lc; + int i = 0; + int status; + + setup(); + + for (lc = 0; TEST_LOOPING(lc); lc++) { + tst_count = 0; + + for (i = 0; i < TST_TOTAL; i++) { + TEST(ltp_clone(test_cases[i].flags, + test_cases[i].do_child, + NULL, CHILD_STACK_SIZE, child_stack, + &ptid, NULL, &ctid)); + + if (TEST_RETURN == -1) { + tst_brkm(TFAIL | TERRNO, cleanup, + "%s clone() failed", + test_cases[i].name); + continue; + } + + if (test_cases[i].testfunc != NULL) + test_cases[i].testfunc(TEST_RETURN); + + if ((test_cases[i].flags & notwait_flag) == 0 && + wait(&status) == -1) { + tst_brkm(TBROK | TERRNO, cleanup, + "wait failed, status: %d", status); + } + } + } + + cleanup(); + tst_exit(); +} + +static void setup(void) +{ + tst_sig(FORK, DEF_HANDLER, cleanup); + TEST_PAUSE; + + parent_ppid = getppid(); + tgid = getpid(); + + child_stack = malloc(CHILD_STACK_SIZE); + if (child_stack == NULL) + tst_brkm(TBROK, cleanup, "Cannot allocate stack for child"); +} + +static void cleanup(void) +{ + free(child_stack); + + TEST_CLEANUP; +} + +static int child_clone_parent() +{ + if (parent_ppid != getppid()) + tst_resm(TFAIL, "test CLONE_PARENT fail"); + else + tst_resm(TPASS, "test CLONE_PARENT success"); + + exit(0); +} + +static int child_clone_child_settid() +{ + if (ctid != getpid()) + tst_resm(TFAIL, "test CLONE_CHILD_SETTID fail"); + else + tst_resm(TPASS, "test CLONE_CHILD_SETTID success"); + + exit(0); +} + +static void test_clone_parent_settid(int tid) +{ + if (tid != ptid) + tst_resm(TFAIL, "test CLONE_PARENT_SETTID fail"); + else + tst_resm(TPASS, "test CLONE_PARENT_SETTID success"); +} + +static int child_clone_parent_settid() +{ + exit(0); +} + + +#ifdef CLONE_STOPPED +static void test_clone_stopped(int tid) +{ + int cnt = 0; + + do { + sleep(1); + } while (thread_state != 1 && cnt++ < 3); + + /* + * if thread_state isn't changed in 3 seconds by child thread, + * we think the child thread has been stopped. + */ + if (thread_state == 0) + tst_resm(TPASS, "test CLONE_STOPPED success"); + else + tst_resm(TFAIL, "test CLONE_STOPPED fail"); + + if (kill(tid, SIGCONT) != 0) + tst_brkm(TBROK | TERRNO, cleanup, "kill SIGCONT failed"); +} +static int child_clone_stopped() +{ + thread_state = 1; + exit(0); +} +#endif -- 1.8.2.1 |
From: <ch...@su...> - 2013-11-14 16:39:16
|
Hi! > --- /dev/null > +++ b/testcases/kernel/syscalls/clone/clone08.c > @@ -0,0 +1,192 @@ > +/* > + * Copyright (c) 2013 Fujitsu Ltd. > + * Author: Zeng Linggang <zen...@cn...> > + * > + * This program is free software; you can redistribute it and/or modify it > + * under the terms of version 2 of the GNU General Public License as > + * published by the Free Software Foundation. > + * > + * This program is distributed in the hope that it would be useful, but > + * WITHOUT ANY WARRANTY; without even the implied warranty of > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. > + * > + * You should have received a copy of the GNU General Public License along > + * with this program; if not, write the Free Software Foundation, Inc., > + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. > + */ > + > +#if defined UCLINUX && !__THROW > +/* workaround for libc bug */ > +#define __THROW > +#endif Adding workarounds for broken toolchanis is no-go. > +#include <errno.h> > +#include <linux/sched.h> > +#include <sys/wait.h> > +#include "test.h" > +#include "usctest.h" > +#include "clone_platform.h" > +#include "linux_syscall_numbers.h" > + > + > +static pid_t parent_ppid; > +static pid_t ptid, ctid; > +static pid_t tgid; > +static void *child_stack; > + > +static void setup(void); > +static void cleanup(void); > + > +static int child_clone_parent(); > +static int child_clone_child_settid(); > +static int child_clone_parent_settid(); Missing void in parameters. > +static void test_clone_parent_settid(int tid); > + > +#ifdef CLONE_STOPPED > +static int thread_state; > +static void test_clone_stopped(int tid); > +static int child_clone_stopped(); > +#endif > + > +static int notwait_flag = CLONE_PARENT; > +static struct test_case { > + char *name; > + int flags; > + void (*testfunc)(int tid); > + int (*do_child)(); > +} test_cases[] = { > + {"CLONE_PARENT", CLONE_PARENT, NULL, child_clone_parent}, > + {"CLONE_CHILD_SETTID", CLONE_CHILD_SETTID | SIGCHLD, NULL, > + child_clone_child_settid}, > + {"CLONE_PARENT_SETTID", CLONE_PARENT_SETTID | SIGCHLD, > + test_clone_parent_settid, child_clone_parent_settid}, > +#ifdef CLONE_STOPPED > + {"CLONE_STOPPED", CLONE_STOPPED | SIGCHLD, test_clone_stopped, > + child_clone_stopped}, > +#endif > +}; > + > +char *TCID = "clone08"; > +int TST_TOTAL = ARRAY_SIZE(test_cases); > + > +int main(int ac, char **av) > +{ > + int lc; > + int i = 0; > + int status; > + > + setup(); > + > + for (lc = 0; TEST_LOOPING(lc); lc++) { > + tst_count = 0; > + > + for (i = 0; i < TST_TOTAL; i++) { > + TEST(ltp_clone(test_cases[i].flags, > + test_cases[i].do_child, > + NULL, CHILD_STACK_SIZE, child_stack, > + &ptid, NULL, &ctid)); > + > + if (TEST_RETURN == -1) { > + tst_brkm(TFAIL | TERRNO, cleanup, ^ It would be better to use TTERRNO instead (because you have used the TEST() macro before) > + "%s clone() failed", > + test_cases[i].name); > + continue; > + } > + > + if (test_cases[i].testfunc != NULL) > + test_cases[i].testfunc(TEST_RETURN); > + > + if ((test_cases[i].flags & notwait_flag) == 0 && > + wait(&status) == -1) { > + tst_brkm(TBROK | TERRNO, cleanup, > + "wait failed, status: %d", status); > + } > + } > + } > + > + cleanup(); > + tst_exit(); > +} > + > +static void setup(void) > +{ > + tst_sig(FORK, DEF_HANDLER, cleanup); > + TEST_PAUSE; > + > + parent_ppid = getppid(); > + tgid = getpid(); > + > + child_stack = malloc(CHILD_STACK_SIZE); > + if (child_stack == NULL) > + tst_brkm(TBROK, cleanup, "Cannot allocate stack for child"); Use SAFE_MALLOC() > +} > + > +static void cleanup(void) > +{ > + free(child_stack); > + > + TEST_CLEANUP; > +} > + > +static int child_clone_parent() > +{ > + if (parent_ppid != getppid()) > + tst_resm(TFAIL, "test CLONE_PARENT fail"); > + else > + tst_resm(TPASS, "test CLONE_PARENT success"); You must not use tst_resm() interface from child, it will not work (the failure will not be propagated to parent). What you need to do is to propagate the test result via return value and use it to determnite test outcome in the parent. > + exit(0); > +} > + > +static int child_clone_child_settid() > +{ > + if (ctid != getpid()) > + tst_resm(TFAIL, "test CLONE_CHILD_SETTID fail"); > + else > + tst_resm(TPASS, "test CLONE_CHILD_SETTID success"); Same here and in the rest of the code. > + exit(0); > +} > + > +static void test_clone_parent_settid(int tid) > +{ > + if (tid != ptid) > + tst_resm(TFAIL, "test CLONE_PARENT_SETTID fail"); > + else > + tst_resm(TPASS, "test CLONE_PARENT_SETTID success"); > +} > + > +static int child_clone_parent_settid() > +{ > + exit(0); > +} > + > + > +#ifdef CLONE_STOPPED > +static void test_clone_stopped(int tid) > +{ > + int cnt = 0; > + > + do { > + sleep(1); > + } while (thread_state != 1 && cnt++ < 3); It's better to use combination of usleep() and sched_yield() like clone05.c does. Idealy just copy the loop from there. > + /* > + * if thread_state isn't changed in 3 seconds by child thread, > + * we think the child thread has been stopped. > + */ > + if (thread_state == 0) > + tst_resm(TPASS, "test CLONE_STOPPED success"); > + else > + tst_resm(TFAIL, "test CLONE_STOPPED fail"); > + > + if (kill(tid, SIGCONT) != 0) > + tst_brkm(TBROK | TERRNO, cleanup, "kill SIGCONT failed"); > +} > +static int child_clone_stopped() > +{ > + thread_state = 1; > + exit(0); > +} > +#endif -- Cyril Hrubis ch...@su... |
From: zenglg.jy <zen...@cn...> - 2013-11-19 14:06:37
|
Add new case for clone(2) with CLONE_PARENT, CLONE_CHILD_SETTID, CLONE_PARENT_SETTID, CLONE_STOPPED, CLONE_THREAD. Signed-off-by: Zeng Linggang <zen...@cn...> --- runtest/ltplite | 1 + runtest/stress.part3 | 1 + runtest/syscalls | 1 + testcases/kernel/syscalls/.gitignore | 1 + testcases/kernel/syscalls/clone/clone08.c | 238 ++++++++++++++++++++++++++++++ 5 files changed, 242 insertions(+) create mode 100644 testcases/kernel/syscalls/clone/clone08.c diff --git a/runtest/ltplite b/runtest/ltplite index f0738c7..71dbb5e 100644 --- a/runtest/ltplite +++ b/runtest/ltplite @@ -126,6 +126,7 @@ clone04 clone04 clone05 clone05 clone06 clone06 clone07 clone07 +clone08 clone08 close01 close01 close02 close02 diff --git a/runtest/stress.part3 b/runtest/stress.part3 index 951b00e..8c42e1b 100644 --- a/runtest/stress.part3 +++ b/runtest/stress.part3 @@ -67,6 +67,7 @@ clone04 clone04 clone05 clone05 clone06 clone06 clone07 clone07 +clone08 clone08 close01 close01 close02 close02 diff --git a/runtest/syscalls b/runtest/syscalls index e5a5508..33cb11c 100644 --- a/runtest/syscalls +++ b/runtest/syscalls @@ -84,6 +84,7 @@ clone04 clone04 clone05 clone05 clone06 clone06 clone07 clone07 +clone08 clone08 close01 close01 close02 close02 diff --git a/testcases/kernel/syscalls/.gitignore b/testcases/kernel/syscalls/.gitignore index 0effa6b..35dd2c5 100644 --- a/testcases/kernel/syscalls/.gitignore +++ b/testcases/kernel/syscalls/.gitignore @@ -64,6 +64,7 @@ /clone/clone05 /clone/clone06 /clone/clone07 +/clone/clone08 /close/close01 /close/close02 /close/close08 diff --git a/testcases/kernel/syscalls/clone/clone08.c b/testcases/kernel/syscalls/clone/clone08.c new file mode 100644 index 0000000..8eebb4d --- /dev/null +++ b/testcases/kernel/syscalls/clone/clone08.c @@ -0,0 +1,238 @@ +/* + * Copyright (c) 2013 Fujitsu Ltd. + * Author: Zeng Linggang <zen...@cn...> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it would be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include <errno.h> +#include <linux/sched.h> +#include <sched.h> +#include <sys/wait.h> +#include "test.h" +#include "usctest.h" +#include "clone_platform.h" +#include "linux_syscall_numbers.h" +#include "safe_macros.h" + +#define PASS 0 +#define FAIL 1 +#define SIG_PASS SIGUSR1 +#define SIG_FAIL SIGUSR2 + + +static pid_t parent_ppid; +static pid_t ptid, ctid; +static pid_t tgid; +static void *child_stack; +static int test_index; + +static void setup(void); +static void cleanup(void); + +static int child_clone_parent(void); +static int child_clone_child_settid(void); +static int child_clone_parent_settid(void); +static int child_clone_thread(void); + +static void test_clone_parent_settid(int tid); +static void sig_func(int signo); + +#ifdef CLONE_STOPPED +static int thread_state; +static void test_clone_stopped(int tid); +static int child_clone_stopped(void); +#endif + +static int notwait_flag = CLONE_PARENT | CLONE_THREAD; +static struct test_case { + char *name; + int flags; + void (*testfunc)(int tid); + int (*do_child)(); +} test_cases[] = { + {"CLONE_PARENT", CLONE_PARENT, NULL, child_clone_parent}, + {"CLONE_CHILD_SETTID", CLONE_CHILD_SETTID | SIGCHLD, NULL, + child_clone_child_settid}, + {"CLONE_PARENT_SETTID", CLONE_PARENT_SETTID | SIGCHLD, + test_clone_parent_settid, child_clone_parent_settid}, +#ifdef CLONE_STOPPED + {"CLONE_STOPPED", CLONE_STOPPED | SIGCHLD, test_clone_stopped, + child_clone_stopped}, +#endif + {"CLONE_THREAD", CLONE_THREAD | CLONE_SIGHAND | CLONE_VM, NULL, + child_clone_thread}, +}; + +char *TCID = "clone08"; +int TST_TOTAL = ARRAY_SIZE(test_cases); + +int main(int ac, char **av) +{ + int lc; + int i = 0; + int status; + + setup(); + + for (lc = 0; TEST_LOOPING(lc); lc++) { + tst_count = 0; + + for (i = 0; i < TST_TOTAL; i++) { + test_index = i; + TEST(ltp_clone(test_cases[i].flags, + test_cases[i].do_child, + NULL, CHILD_STACK_SIZE, child_stack, + &ptid, NULL, &ctid)); + + if (TEST_RETURN == -1) { + tst_brkm(TFAIL | TTERRNO, cleanup, + "%s clone() failed", + test_cases[i].name); + continue; + } + + if (test_cases[i].testfunc != NULL) + test_cases[i].testfunc(TEST_RETURN); + + if ((test_cases[i].flags & notwait_flag) == 0) { + if (wait(&status) == -1) { + tst_brkm(TBROK | TERRNO, cleanup, + "wait failed, status: %d", + status); + } + if (test_cases[i].testfunc != NULL) + continue; + if (WIFEXITED(status) && + WEXITSTATUS(status) == PASS) { + tst_resm(TPASS, "test %s success", + test_cases[i].name); + } else { + tst_resm(TFAIL, "test %s fail", + test_cases[i].name); + } + } else { + /* + * wait cloned thread to wake us, and verify + * the test result in the signal hander + */ + pause(); + } + } + } + + cleanup(); + tst_exit(); +} + +static void setup(void) +{ + tst_sig(FORK, DEF_HANDLER, cleanup); + TEST_PAUSE; + + parent_ppid = getppid(); + tgid = getpid(); + + if (signal(SIG_PASS, sig_func) == SIG_ERR) + tst_brkm(TBROK | TERRNO, cleanup, "signal failed"); + if (signal(SIG_FAIL, sig_func) == SIG_ERR) + tst_brkm(TBROK | TERRNO, cleanup, "signal failed"); + + child_stack = SAFE_MALLOC(cleanup, CHILD_STACK_SIZE); +} + +static void cleanup(void) +{ + free(child_stack); + + TEST_CLEANUP; +} + +static int child_clone_parent() +{ + usleep(500000); + if (parent_ppid == getppid()) + kill(tgid, SIG_PASS); + else + kill(tgid, SIG_FAIL); + exit(PASS); +} + +static void sig_func(int signo) +{ + if (signo != SIG_PASS) + tst_resm(TFAIL, "test %s fail", test_cases[test_index].name); + else + tst_resm(TPASS, "test %s success", test_cases[test_index].name); +} + +static int child_clone_child_settid() +{ + if (ctid != getpid()) + exit(FAIL); + else + exit(PASS); +} + +static void test_clone_parent_settid(int tid) +{ + if (tid != ptid) + tst_resm(TFAIL, "test CLONE_PARENT_SETTID fail"); + else + tst_resm(TPASS, "test CLONE_PARENT_SETTID success"); +} + +static int child_clone_parent_settid() +{ + exit(PASS); +} + +#ifdef CLONE_STOPPED +static void test_clone_stopped(int tid) +{ + int i; + + /* give the kernel scheduler chance to run the child */ + for (i = 0; i < 100; i++) { + sched_yield(); + usleep(1000); + } + if (thread_state == 0) + tst_resm(TPASS, "test CLONE_STOPPED success"); + else + tst_resm(TFAIL, "test CLONE_STOPPED fail"); + + if (kill(tid, SIGCONT) != 0) + tst_brkm(TBROK | TERRNO, cleanup, "kill SIGCONT failed"); +} + +static int child_clone_stopped() +{ + thread_state = 1; + exit(PASS); +} +#endif + +static int child_clone_thread(void) +{ + pid_t child_tgid; + + child_tgid = getpid(); + + if (tgid == child_tgid) + kill(tgid, SIG_PASS); + else + kill(tgid, SIG_FAIL); + usleep(500000); + exit(PASS); +} -- 1.8.2.1 |
From: Jan S. <jst...@re...> - 2013-11-20 09:11:22
|
----- Original Message ----- > From: "zenglg.jy" <zen...@cn...> > To: "chrubis" <ch...@su...> > Cc: "ltp-list" <ltp...@li...> > Sent: Tuesday, 19 November, 2013 3:06:20 PM > Subject: [LTP] [PATCH v2] clone/clone08.c: Add new flags > > Add new case for clone(2) with CLONE_PARENT, CLONE_CHILD_SETTID, > CLONE_PARENT_SETTID, CLONE_STOPPED, CLONE_THREAD. > > Signed-off-by: Zeng Linggang <zen...@cn...> > --- > runtest/ltplite | 1 + > runtest/stress.part3 | 1 + > runtest/syscalls | 1 + > testcases/kernel/syscalls/.gitignore | 1 + > testcases/kernel/syscalls/clone/clone08.c | 238 > ++++++++++++++++++++++++++++++ > 5 files changed, 242 insertions(+) > create mode 100644 testcases/kernel/syscalls/clone/clone08.c > > diff --git a/runtest/ltplite b/runtest/ltplite > index f0738c7..71dbb5e 100644 > --- a/runtest/ltplite > +++ b/runtest/ltplite > @@ -126,6 +126,7 @@ clone04 clone04 > clone05 clone05 > clone06 clone06 > clone07 clone07 > +clone08 clone08 > > close01 close01 > close02 close02 > diff --git a/runtest/stress.part3 b/runtest/stress.part3 > index 951b00e..8c42e1b 100644 > --- a/runtest/stress.part3 > +++ b/runtest/stress.part3 > @@ -67,6 +67,7 @@ clone04 clone04 > clone05 clone05 > clone06 clone06 > clone07 clone07 > +clone08 clone08 > > close01 close01 > close02 close02 > diff --git a/runtest/syscalls b/runtest/syscalls > index e5a5508..33cb11c 100644 > --- a/runtest/syscalls > +++ b/runtest/syscalls > @@ -84,6 +84,7 @@ clone04 clone04 > clone05 clone05 > clone06 clone06 > clone07 clone07 > +clone08 clone08 > > close01 close01 > close02 close02 > diff --git a/testcases/kernel/syscalls/.gitignore > b/testcases/kernel/syscalls/.gitignore > index 0effa6b..35dd2c5 100644 > --- a/testcases/kernel/syscalls/.gitignore > +++ b/testcases/kernel/syscalls/.gitignore > @@ -64,6 +64,7 @@ > /clone/clone05 > /clone/clone06 > /clone/clone07 > +/clone/clone08 > /close/close01 > /close/close02 > /close/close08 > diff --git a/testcases/kernel/syscalls/clone/clone08.c > b/testcases/kernel/syscalls/clone/clone08.c > new file mode 100644 > index 0000000..8eebb4d > --- /dev/null > +++ b/testcases/kernel/syscalls/clone/clone08.c > @@ -0,0 +1,238 @@ > +/* > + * Copyright (c) 2013 Fujitsu Ltd. > + * Author: Zeng Linggang <zen...@cn...> > + * > + * This program is free software; you can redistribute it and/or modify it > + * under the terms of version 2 of the GNU General Public License as > + * published by the Free Software Foundation. > + * > + * This program is distributed in the hope that it would be useful, but > + * WITHOUT ANY WARRANTY; without even the implied warranty of > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. > + * > + * You should have received a copy of the GNU General Public License along > + * with this program; if not, write the Free Software Foundation, Inc., > + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. > + */ > + > +#include <errno.h> > +#include <linux/sched.h> > +#include <sched.h> > +#include <sys/wait.h> > +#include "test.h" > +#include "usctest.h" > +#include "clone_platform.h" > +#include "linux_syscall_numbers.h" > +#include "safe_macros.h" > + > +#define PASS 0 > +#define FAIL 1 > +#define SIG_PASS SIGUSR1 > +#define SIG_FAIL SIGUSR2 > + > + > +static pid_t parent_ppid; > +static pid_t ptid, ctid; > +static pid_t tgid; > +static void *child_stack; > +static int test_index; > + > +static void setup(void); > +static void cleanup(void); > + > +static int child_clone_parent(void); > +static int child_clone_child_settid(void); > +static int child_clone_parent_settid(void); > +static int child_clone_thread(void); > + > +static void test_clone_parent_settid(int tid); > +static void sig_func(int signo); > + > +#ifdef CLONE_STOPPED > +static int thread_state; > +static void test_clone_stopped(int tid); > +static int child_clone_stopped(void); > +#endif > + > +static int notwait_flag = CLONE_PARENT | CLONE_THREAD; > +static struct test_case { > + char *name; > + int flags; > + void (*testfunc)(int tid); > + int (*do_child)(); > +} test_cases[] = { > + {"CLONE_PARENT", CLONE_PARENT, NULL, child_clone_parent}, > + {"CLONE_CHILD_SETTID", CLONE_CHILD_SETTID | SIGCHLD, NULL, > + child_clone_child_settid}, > + {"CLONE_PARENT_SETTID", CLONE_PARENT_SETTID | SIGCHLD, > + test_clone_parent_settid, child_clone_parent_settid}, > +#ifdef CLONE_STOPPED > + {"CLONE_STOPPED", CLONE_STOPPED | SIGCHLD, test_clone_stopped, > + child_clone_stopped}, > +#endif > + {"CLONE_THREAD", CLONE_THREAD | CLONE_SIGHAND | CLONE_VM, NULL, > + child_clone_thread}, > +}; > + > +char *TCID = "clone08"; > +int TST_TOTAL = ARRAY_SIZE(test_cases); > + > +int main(int ac, char **av) > +{ > + int lc; > + int i = 0; > + int status; > + > + setup(); > + > + for (lc = 0; TEST_LOOPING(lc); lc++) { > + tst_count = 0; > + > + for (i = 0; i < TST_TOTAL; i++) { > + test_index = i; > + TEST(ltp_clone(test_cases[i].flags, > + test_cases[i].do_child, > + NULL, CHILD_STACK_SIZE, child_stack, > + &ptid, NULL, &ctid)); > + > + if (TEST_RETURN == -1) { > + tst_brkm(TFAIL | TTERRNO, cleanup, > + "%s clone() failed", > + test_cases[i].name); > + continue; > + } > + > + if (test_cases[i].testfunc != NULL) > + test_cases[i].testfunc(TEST_RETURN); > + > + if ((test_cases[i].flags & notwait_flag) == 0) { > + if (wait(&status) == -1) { > + tst_brkm(TBROK | TERRNO, cleanup, > + "wait failed, status: %d", > + status); > + } > + if (test_cases[i].testfunc != NULL) > + continue; > + if (WIFEXITED(status) && > + WEXITSTATUS(status) == PASS) { > + tst_resm(TPASS, "test %s success", > + test_cases[i].name); > + } else { > + tst_resm(TFAIL, "test %s fail", > + test_cases[i].name); > + } > + } else { > + /* > + * wait cloned thread to wake us, and verify > + * the test result in the signal hander > + */ > + pause(); > + } > + } > + } > + > + cleanup(); > + tst_exit(); > +} > + > +static void setup(void) > +{ > + tst_sig(FORK, DEF_HANDLER, cleanup); > + TEST_PAUSE; > + > + parent_ppid = getppid(); > + tgid = getpid(); > + > + if (signal(SIG_PASS, sig_func) == SIG_ERR) > + tst_brkm(TBROK | TERRNO, cleanup, "signal failed"); > + if (signal(SIG_FAIL, sig_func) == SIG_ERR) > + tst_brkm(TBROK | TERRNO, cleanup, "signal failed"); > + > + child_stack = SAFE_MALLOC(cleanup, CHILD_STACK_SIZE); > +} > + > +static void cleanup(void) > +{ > + free(child_stack); > + > + TEST_CLEANUP; > +} > + > +static int child_clone_parent() > +{ > + usleep(500000); > + if (parent_ppid == getppid()) > + kill(tgid, SIG_PASS); > + else > + kill(tgid, SIG_FAIL); > + exit(PASS); > +} Hi, why not just exit with either PASS or FAIL and parent can check the status? You wouldn't need sleep or signals. If you need parent/child synchronization, then consider "checkpoints" (lib/tst_checkpoint.c) > + > +static void sig_func(int signo) > +{ > + if (signo != SIG_PASS) > + tst_resm(TFAIL, "test %s fail", test_cases[test_index].name); > + else > + tst_resm(TPASS, "test %s success", test_cases[test_index].name); > +} > + > +static int child_clone_child_settid() > +{ > + if (ctid != getpid()) > + exit(FAIL); > + else > + exit(PASS); > +} > + > +static void test_clone_parent_settid(int tid) > +{ > + if (tid != ptid) > + tst_resm(TFAIL, "test CLONE_PARENT_SETTID fail"); > + else > + tst_resm(TPASS, "test CLONE_PARENT_SETTID success"); > +} > + > +static int child_clone_parent_settid() > +{ > + exit(PASS); > +} > + > +#ifdef CLONE_STOPPED > +static void test_clone_stopped(int tid) > +{ > + int i; > + > + /* give the kernel scheduler chance to run the child */ > + for (i = 0; i < 100; i++) { > + sched_yield(); > + usleep(1000); > + } > + if (thread_state == 0) Does the child have even chance to change this value in parent without CLONE_VM? > + tst_resm(TPASS, "test CLONE_STOPPED success"); > + else > + tst_resm(TFAIL, "test CLONE_STOPPED fail"); > + > + if (kill(tid, SIGCONT) != 0) > + tst_brkm(TBROK | TERRNO, cleanup, "kill SIGCONT failed"); > +} > + > +static int child_clone_stopped() > +{ > + thread_state = 1; thread_state should be reset to 0 before this test, in case you run it in loop (-i parameter). > + exit(PASS); > +} > +#endif > + > +static int child_clone_thread(void) > +{ > + pid_t child_tgid; > + > + child_tgid = getpid(); > + > + if (tgid == child_tgid) > + kill(tgid, SIG_PASS); > + else > + kill(tgid, SIG_FAIL); > + usleep(500000); > + exit(PASS); > +} Same as above, why not just return PASS or FAIL and check status in parent? Regards, Jan > -- > 1.8.2.1 > > > > > ------------------------------------------------------------------------------ > Shape the Mobile Experience: Free Subscription > Software experts and developers: Be at the forefront of tech innovation. > Intel(R) Software Adrenaline delivers strategic insight and game-changing > conversations that shape the rapidly evolving mobile landscape. Sign up now. > http://pubads.g.doubleclick.net/gampad/clk?id=63431311&iu=/4140/ostg.clktrk > _______________________________________________ > Ltp-list mailing list > Ltp...@li... > https://lists.sourceforge.net/lists/listinfo/ltp-list > |
From: zenglg.jy <zen...@cn...> - 2013-11-25 09:11:56
|
On Wed, 2013-11-20 at 04:11 -0500, Jan Stancek wrote: > > +static int child_clone_parent() > > +{ > > + usleep(500000); > > + if (parent_ppid == getppid()) > > + kill(tgid, SIG_PASS); > > + else > > + kill(tgid, SIG_FAIL); > > + exit(PASS); > > +} > > Hi, > > why not just exit with either PASS or FAIL and parent can check the status? > You wouldn't need sleep or signals. > > If you need parent/child synchronization, then consider "checkpoints" (lib/tst_checkpoint.c) > There is a little different with CLONE_PARENT. The exit value can't be easily gained by the calling process(after CLONE_PARENT, they are not really parent and child, maybe brothers precise). wait(&status); /* It will faile because of no child. */ if (WIFEXITED(status) && WEXITSTATUS(status) == PASS) ... > > +#ifdef CLONE_STOPPED > > +static void test_clone_stopped(int tid) > > +{ > > + int i; > > + > > + /* give the kernel scheduler chance to run the child */ > > + for (i = 0; i < 100; i++) { > > + sched_yield(); > > + usleep(1000); > > + } > > + if (thread_state == 0) > > Does the child have even chance to change this value in parent without CLONE_VM? > Yes, we should add CLONE_VM. > > + tst_resm(TPASS, "test CLONE_STOPPED success"); > > + else > > + tst_resm(TFAIL, "test CLONE_STOPPED fail"); > > + > > + if (kill(tid, SIGCONT) != 0) > > + tst_brkm(TBROK | TERRNO, cleanup, "kill SIGCONT failed"); > > +} > > + > > +static int child_clone_stopped() > > +{ > > + thread_state = 1; > > thread_state should be reset to 0 before this test, in case you run it in loop (-i parameter). > Yes, thread_state should be reset to 0 at the begin of the loop. > > + exit(PASS); > > +} > > +#endif > > + > > +static int child_clone_thread(void) > > +{ > > + pid_t child_tgid; > > + > > + child_tgid = getpid(); > > + > > + if (tgid == child_tgid) > > + kill(tgid, SIG_PASS); > > + else > > + kill(tgid, SIG_FAIL); > > + usleep(500000); > > + exit(PASS); > > +} > > Same as above, why not just return PASS or FAIL and check status in parent? > When a CLONE_THREAD thread terminates, the thread that created it using clone() is not sent a SIGCHLD (or other termination) signal; nor can the status of such a thread be obtained using wait(2). (The thread is said to be detached.) best regards, Zeng > Regards, > Jan |
From: Jan S. <jst...@re...> - 2013-11-25 16:32:40
|
----- Original Message ----- > From: "zenglg.jy" <zen...@cn...> > To: "Jan Stancek" <jst...@re...> > Cc: "chrubis" <ch...@su...>, "ltp-list" <ltp...@li...> > Sent: Monday, 25 November, 2013 10:11:22 AM > Subject: Re: [LTP] [PATCH v2] clone/clone08.c: Add new flags > > On Wed, 2013-11-20 at 04:11 -0500, Jan Stancek wrote: > > > +static int child_clone_parent() > > > +{ > > > + usleep(500000); > > > + if (parent_ppid == getppid()) > > > + kill(tgid, SIG_PASS); > > > + else > > > + kill(tgid, SIG_FAIL); > > > + exit(PASS); > > > +} > > > > Hi, > > > > why not just exit with either PASS or FAIL and parent can check the status? > > You wouldn't need sleep or signals. > > > > If you need parent/child synchronization, then consider "checkpoints" > > (lib/tst_checkpoint.c) > > > > There is a little different with CLONE_PARENT. The exit value can't be > easily gained by the calling process(after CLONE_PARENT, they are not > really parent and child, maybe brothers precise). > wait(&status); /* It will faile because of no child. */ > if (WIFEXITED(status) && WEXITSTATUS(status) == PASS) > ... > > > > +#ifdef CLONE_STOPPED > > > +static void test_clone_stopped(int tid) > > > +{ > > > + int i; > > > + > > > + /* give the kernel scheduler chance to run the child */ > > > + for (i = 0; i < 100; i++) { > > > + sched_yield(); > > > + usleep(1000); > > > + } > > > + if (thread_state == 0) > > > > Does the child have even chance to change this value in parent without > > CLONE_VM? > > > > Yes, we should add CLONE_VM. > > > > + tst_resm(TPASS, "test CLONE_STOPPED success"); > > > + else > > > + tst_resm(TFAIL, "test CLONE_STOPPED fail"); > > > + > > > + if (kill(tid, SIGCONT) != 0) > > > + tst_brkm(TBROK | TERRNO, cleanup, "kill SIGCONT failed"); > > > +} > > > + > > > +static int child_clone_stopped() > > > +{ > > > + thread_state = 1; > > > > thread_state should be reset to 0 before this test, in case you run it in > > loop (-i parameter). > > > > Yes, thread_state should be reset to 0 at the begin of the loop. > > > > + exit(PASS); > > > +} > > > +#endif > > > + > > > +static int child_clone_thread(void) > > > +{ > > > + pid_t child_tgid; > > > + > > > + child_tgid = getpid(); > > > + > > > + if (tgid == child_tgid) > > > + kill(tgid, SIG_PASS); > > > + else > > > + kill(tgid, SIG_FAIL); > > > + usleep(500000); > > > + exit(PASS); > > > +} > > > > Same as above, why not just return PASS or FAIL and check status in parent? > > > > When a CLONE_THREAD thread terminates, the thread that created it using > clone() is not sent a SIGCHLD (or other termination) signal; nor can the > status of such a thread be obtained using wait(2). (The thread is said to > be detached.) I see. But still I'd like to find a way to do it without those sleeps. If we use checkpoints and signal parent only in good case, then failed run will get aborted with TBROK, as there is built-in timeout. Or other idea: Make one more fork so we have a pid to wait for and call clone(CLONE_THREAD) inside. from man 2 clone: "After all of the threads in a thread group terminate the parent process of the thread group is sent a SIGCHLD (or other termination) signal." Any thoughts? Regards, Jan > > best regards, > Zeng > > > Regards, > > Jan > > > |
From: zenglg.jy <zen...@cn...> - 2013-12-09 12:06:44
|
>From 0b159a7cf724a698e9ce087932249a6d9f1b701e Mon Sep 17 00:00:00 2001 From: Zeng Linggang <zen...@cn...> Date: Mon, 9 Dec 2013 19:37:38 +0800 Subject: [PATCH] clone/clone08.c: Add new flags Add new case for clone(2) CLONE_PARENT CLONE_CHILD_SETTID CLONE_PARENT_SETTID CLONE_STOPPED CLONE_THREAD Signed-off-by: Zeng Linggang <zen...@cn...> --- runtest/ltplite | 1 + runtest/stress.part3 | 1 + runtest/syscalls | 1 + testcases/kernel/syscalls/.gitignore | 1 + testcases/kernel/syscalls/clone/clone08.c | 301 ++++++++++++++++++++++++++++++ 5 files changed, 305 insertions(+) create mode 100644 testcases/kernel/syscalls/clone/clone08.c diff --git a/runtest/ltplite b/runtest/ltplite index 2382dec..fe6cb04 100644 --- a/runtest/ltplite +++ b/runtest/ltplite @@ -127,6 +127,7 @@ clone04 clone04 clone05 clone05 clone06 clone06 clone07 clone07 +clone08 clone08 close01 close01 close02 close02 diff --git a/runtest/stress.part3 b/runtest/stress.part3 index 16247e9..16b08a7 100644 --- a/runtest/stress.part3 +++ b/runtest/stress.part3 @@ -68,6 +68,7 @@ clone04 clone04 clone05 clone05 clone06 clone06 clone07 clone07 +clone08 clone08 close01 close01 close02 close02 diff --git a/runtest/syscalls b/runtest/syscalls index 12bae10..14bcd88 100644 --- a/runtest/syscalls +++ b/runtest/syscalls @@ -85,6 +85,7 @@ clone04 clone04 clone05 clone05 clone06 clone06 clone07 clone07 +clone08 clone08 close01 close01 close02 close02 diff --git a/testcases/kernel/syscalls/.gitignore b/testcases/kernel/syscalls/.gitignore index 218ec0c..8c19551 100644 --- a/testcases/kernel/syscalls/.gitignore +++ b/testcases/kernel/syscalls/.gitignore @@ -65,6 +65,7 @@ /clone/clone05 /clone/clone06 /clone/clone07 +/clone/clone08 /close/close01 /close/close02 /close/close08 diff --git a/testcases/kernel/syscalls/clone/clone08.c b/testcases/kernel/syscalls/clone/clone08.c new file mode 100644 index 0000000..1c49888 --- /dev/null +++ b/testcases/kernel/syscalls/clone/clone08.c @@ -0,0 +1,301 @@ +/* + * Copyright (c) 2013 Fujitsu Ltd. + * Author: Zeng Linggang <zen...@cn...> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it would be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#if defined UCLINUX && !__THROW +/* workaround for libc bug */ +#define __THROW +#endif + +#include <errno.h> +#include <linux/sched.h> +#include <sched.h> +#include <sys/wait.h> +#include "test.h" +#include "usctest.h" +#include "clone_platform.h" +#include "safe_macros.h" +#include "linux_syscall_numbers.h" + +#define PASS 0 +#define FAIL 1 + +static pid_t parent_ppid; +static pid_t ptid, ctid; +static pid_t tgid; +static void *child_stack; +static int tst_result; + +static void setup(void); +static void cleanup(void); +static void do_master_child_setup(void); +static void do_master_child(void); + +static int child_clone_parent(void); +static void wait_process_terminated(int pid); +static int child_clone_child_settid(void); +static int child_clone_parent_settid(void); +static int child_clone_thread(void); + +#ifdef CLONE_STOPPED +static int stopped_flag; +static void test_clone_stopped(int tid); +static int child_clone_stopped(void); +#endif + +static struct test_case { + char *name; + int flags; + void (*testfunc)(int); + int (*do_child)(); +} test_cases[] = { + {"CLONE_PARENT", CLONE_PARENT | CLONE_VM | SIGCHLD, NULL, + child_clone_parent}, + {"CLONE_CHILD_SETTID", CLONE_CHILD_SETTID | CLONE_VM | SIGCHLD, NULL, + child_clone_child_settid}, + {"CLONE_PARENT_SETTID", CLONE_PARENT_SETTID | CLONE_VM | SIGCHLD, NULL, + child_clone_parent_settid}, +#ifdef CLONE_STOPPED + {"CLONE_STOPPED", CLONE_STOPPED | CLONE_VM | SIGCHLD, + test_clone_stopped, child_clone_stopped}, +#endif + {"CLONE_THREAD", CLONE_THREAD | CLONE_SIGHAND | CLONE_VM | SIGCHLD, + NULL, child_clone_thread}, +}; + +char *TCID = "clone08"; +int TST_TOTAL = ARRAY_SIZE(test_cases); + +static struct tst_checkpoint checkpoint; + +int main(int ac, char **av) +{ + char *msg; + pid_t child_pid; + pid_t exit_child_pid; + int status; + + msg = parse_opts(ac, av, NULL, NULL); + if (msg != NULL) + tst_brkm(TBROK, NULL, "OPTION PARSING ERROR - %s", msg); + + setup(); + + child_pid = FORK_OR_VFORK(); + if (child_pid < 0) { + tst_brkm(TBROK, cleanup, "Fork failed"); + } else if (child_pid == 0) { + do_master_child(); + } else { + /* wait child and CLONE_PARENT */ + while (1) { + exit_child_pid = waitpid(-1, &status, WNOHANG); + if (exit_child_pid == -1) { + break; + } else if (exit_child_pid == 0) { + sched_yield(); + usleep(1000); + } else { + if (!WIFEXITED(status) || + (WEXITSTATUS(status) != 0)) { + tst_resm(TFAIL, + "son process exits error"); + } + } + } + } + + cleanup(); + tst_exit(); +} + +static void do_master_child_setup(void) +{ + parent_ppid = getppid(); + + tgid = getpid(); + + TST_CHECKPOINT_INIT(&checkpoint); +} + +static void do_master_child(void) +{ + int lc; + int i; + int status; + + do_master_child_setup(); + + for (lc = 0; TEST_LOOPING(lc); lc++) { + tst_count = 0; + +#ifdef CLONE_STOPPED + stopped_flag = 0; +#endif + for (i = 0; i < TST_TOTAL; i++) { + tst_result = FAIL; + + TEST(ltp_clone(test_cases[i].flags, + test_cases[i].do_child, NULL, CHILD_STACK_SIZE, + child_stack, &ptid, NULL, &ctid)); + + if (TEST_RETURN == -1) { + tst_resm(TFAIL | TTERRNO, "%s clone() failed", + test_cases[i].name); + continue; + } + + if (test_cases[i].testfunc != NULL) + test_cases[i].testfunc(TEST_RETURN); + + if (test_cases[i].flags & CLONE_PARENT) { + wait_process_terminated(TEST_RETURN); + } else if (test_cases[i].flags & CLONE_THREAD) { + TST_CHECKPOINT_PARENT_WAIT(NULL, + &checkpoint); + } else { + if (wait(&status) == -1) { + tst_brkm(TBROK | TERRNO, NULL, + "wait failed, status: %d", + status); + } + } + + if (tst_result == PASS) { + tst_resm(TPASS, "test %s success", + test_cases[i].name); + } else { + tst_resm(TFAIL, "test %s fail", + test_cases[i].name); + } + } + } + + tst_exit(); +} + +static void setup(void) +{ + tst_sig(FORK, DEF_HANDLER, cleanup); + + TEST_PAUSE; + + tst_tmpdir(); + + child_stack = SAFE_MALLOC(cleanup, CHILD_STACK_SIZE); +} + +static void cleanup(void) +{ + free(child_stack); + + tst_rmdir(); + + TEST_CLEANUP; +} + +static int child_clone_parent(void) +{ + if (parent_ppid == getppid()) + tst_result = PASS; + else + tst_result = FAIL; + exit(0); +} + +/* + * for CLONE_PARENT thread, the calling process can't get its + * status using wait(2), so here using kill(pid, 0) to ensure + * the CLONE_PARENT thread does not exist. + */ +static void wait_process_terminated(int pid) +{ + int ret; + + while (1) { + ret = kill(pid, 0); + if (ret == 0) { + sched_yield(); + usleep(1000); + continue; + } + if (errno == ESRCH) + break; + } +} + +static int child_clone_child_settid(void) +{ + if (ctid == getpid()) + tst_result = PASS; + else + tst_result = FAIL; + + exit(tst_result); +} + +static int child_clone_parent_settid(void) +{ + if (ptid == getpid()) + tst_result = PASS; + else + tst_result = FAIL; + + exit(tst_result); +} + +#ifdef CLONE_STOPPED +static void test_clone_stopped(int tid) +{ + int i; + + /* give the kernel scheduler chance to run the CLONE_STOPPED thread*/ + for (i = 0; i < 100; i++) { + sched_yield(); + usleep(1000); + } + /* + * if stopped_flag is not changed in the above time interval, + * we think the CLONE_STOPPED thread is stopped. + */ + if (stopped_flag == 1) + tst_result = FAIL; + else + tst_result = PASS; + + if (kill(tid, SIGCONT) != 0) + tst_brkm(TBROK | TERRNO, cleanup, "kill SIGCONT failed"); +} + +static int child_clone_stopped(void) +{ + stopped_flag = 1; + exit(tst_result); +} +#endif + +static int child_clone_thread(void) +{ + if (tgid == getpid()) + tst_result = PASS; + else + tst_result = FAIL; + + TST_CHECKPOINT_SIGNAL_PARENT(&checkpoint); + + ltp_syscall(__NR_exit); + return 0; +} -- 1.8.2.1 |
From: Jan S. <jst...@re...> - 2013-12-09 16:15:46
|
----- Original Message ----- > From: "zenglg.jy" <zen...@cn...> > To: "Jan Stancek" <jst...@re...> > Cc: "ltp-list" <ltp...@li...> > Sent: Monday, 9 December, 2013 1:06:26 PM > Subject: [PATCH v3 2/2] clone/clone08.c: Add new flags > Hi, <snip> > +#if defined UCLINUX && !__THROW > +/* workaround for libc bug */ > +#define __THROW > +#endif This workaround appeared again in v3, while the v2 has it removed after comment from Cyril. > +#include <errno.h> > +#include <linux/sched.h> > +#include <sched.h> > +#include <sys/wait.h> > +#include "test.h" > +#include "usctest.h" > +#include "clone_platform.h" > +#include "safe_macros.h" > +#include "linux_syscall_numbers.h" > + > +#define PASS 0 > +#define FAIL 1 I think TPASS and TFAIL are defined exactly the same. > +int main(int ac, char **av) > +{ > + char *msg; > + pid_t child_pid; > + pid_t exit_child_pid; > + int status; > + > + msg = parse_opts(ac, av, NULL, NULL); > + if (msg != NULL) > + tst_brkm(TBROK, NULL, "OPTION PARSING ERROR - %s", msg); > + > + setup(); > + > + child_pid = FORK_OR_VFORK(); > + if (child_pid < 0) { > + tst_brkm(TBROK, cleanup, "Fork failed"); > + } else if (child_pid == 0) { > + do_master_child(); > + } else { > + /* wait child and CLONE_PARENT */ > + while (1) { > + exit_child_pid = waitpid(-1, &status, WNOHANG); > + if (exit_child_pid == -1) { > + break; > + } else if (exit_child_pid == 0) { > + sched_yield(); > + usleep(1000); > + } else { > + if (!WIFEXITED(status) || > + (WEXITSTATUS(status) != 0)) { > + tst_resm(TFAIL, > + "son process exits error"); Printing the actual 'status' value could be helpful if it fails. > +static void do_master_child(void) > +{ > + int lc; > + int i; > + int status; > + > + do_master_child_setup(); > + > + for (lc = 0; TEST_LOOPING(lc); lc++) { > + tst_count = 0; > + > +#ifdef CLONE_STOPPED > + stopped_flag = 0; > +#endif > + for (i = 0; i < TST_TOTAL; i++) { > + tst_result = FAIL; > + > + TEST(ltp_clone(test_cases[i].flags, > + test_cases[i].do_child, NULL, CHILD_STACK_SIZE, > + child_stack, &ptid, NULL, &ctid)); > + > + if (TEST_RETURN == -1) { > + tst_resm(TFAIL | TTERRNO, "%s clone() failed", > + test_cases[i].name); > + continue; > + } > + > + if (test_cases[i].testfunc != NULL) > + test_cases[i].testfunc(TEST_RETURN); > + > + if (test_cases[i].flags & CLONE_PARENT) { > + wait_process_terminated(TEST_RETURN); > + } else if (test_cases[i].flags & CLONE_THREAD) { > + TST_CHECKPOINT_PARENT_WAIT(NULL, > + &checkpoint); > + } else { > + if (wait(&status) == -1) { > + tst_brkm(TBROK | TERRNO, NULL, > + "wait failed, status: %d", > + status); > + } > + } > + > + if (tst_result == PASS) { > + tst_resm(TPASS, "test %s success", > + test_cases[i].name); > + } else { > + tst_resm(TFAIL, "test %s fail", > + test_cases[i].name); > + } > + } > + } > + > + tst_exit(); > +} Use of tst_ functions in child processes is discouraged. +static int child_clone_thread(void) +{ + if (tgid == getpid()) + tst_result = PASS; + else + tst_result = FAIL; + + TST_CHECKPOINT_SIGNAL_PARENT(&checkpoint); + + ltp_syscall(__NR_exit); Exit syscall is defined with parameter "error_code": SYSCALL_DEFINE1(exit, int, error_code) + return 0; +} I was running v3 with only "CLONE_THREAD" testcase enabled: - {"CLONE_PARENT", CLONE_PARENT | CLONE_VM | SIGCHLD, NULL, - child_clone_parent}, - {"CLONE_CHILD_SETTID", CLONE_CHILD_SETTID | CLONE_VM | SIGCHLD, NULL, - child_clone_child_settid}, - {"CLONE_PARENT_SETTID", CLONE_PARENT_SETTID | CLONE_VM | SIGCHLD, NULL, - child_clone_parent_settid}, -#ifdef CLONE_STOPPED - {"CLONE_STOPPED", CLONE_STOPPED | CLONE_VM | SIGCHLD, - test_clone_stopped, child_clone_stopped}, -#endif and I see it failing/crashing sometimes. I usually see one of these failures: 1. clone08 4 TBROK : Failed to read from pipe at clone08.c:168: errno=EAGAIN(11): Resource temporarily unavailable 2. clone08 1 TBROK : The other end of the pipe was closed unexpectedly at clone08.c:168 3. clone08 4 TPASS : test CLONE_THREAD success clone08 1 TBROK : unexpected signal 11 received (pid = 8234). clone08 2 TBROK : Remaining cases broken clone08 1 TFAIL : son process exits error 4. no error, but test doesn't execute as many times as specified on command line I'm running it on RHEL6.5 (2.6.32-431.el6) as unprivileged user in following way: # ./clone08 -i 1000 or # ./clone08 -i 1000 | grep TPASS | wc -l and expecting to get number 1000 on output, but I'm getting random numbers I tried also RHEL7 Beta as root user and saw one more: 5. clone08 1 TBROK : unexpected signal 4 received (pid = 28936). Regards, Jan |
From: Jan S. <jst...@re...> - 2013-12-10 07:54:15
|
----- Original Message ----- > From: "Jan Stancek" <jst...@re...> > To: "zenglg.jy" <zen...@cn...> > Cc: "ltp-list" <ltp...@li...> > Sent: Monday, 9 December, 2013 5:15:32 PM > Subject: Re: [LTP] [PATCH v3 2/2] clone/clone08.c: Add new flags > > > > I was running v3 with only "CLONE_THREAD" testcase enabled: > - {"CLONE_PARENT", CLONE_PARENT | CLONE_VM | SIGCHLD, NULL, > - child_clone_parent}, > - {"CLONE_CHILD_SETTID", CLONE_CHILD_SETTID | CLONE_VM | SIGCHLD, NULL, > - child_clone_child_settid}, > - {"CLONE_PARENT_SETTID", CLONE_PARENT_SETTID | CLONE_VM | SIGCHLD, > NULL, > - child_clone_parent_settid}, > -#ifdef CLONE_STOPPED > - {"CLONE_STOPPED", CLONE_STOPPED | CLONE_VM | SIGCHLD, > - test_clone_stopped, child_clone_stopped}, > -#endif > > and I see it failing/crashing sometimes. I usually see one of these failures: > > 1. clone08 4 TBROK : Failed to read from pipe at clone08.c:168: > errno=EAGAIN(11): Resource temporarily unavailable > 2. clone08 1 TBROK : The other end of the pipe was closed unexpectedly > at clone08.c:168 > 3. clone08 4 TPASS : test CLONE_THREAD success > clone08 1 TBROK : unexpected signal 11 received (pid = 8234). > clone08 2 TBROK : Remaining cases broken > clone08 1 TFAIL : son process exits error > 4. no error, but test doesn't execute as many times as specified on command > line > 5. clone08 1 TBROK : unexpected signal 4 received (pid = 28936). Some of above are caused by multiple threads reusing same stack area. Trouble is that with single master child you can't be sure when CLONE_THREAD child finished using its stack. The idea I mentioned in v2 was basically what you did, but the loop for testcases would be outside master child - which means spawning master_child for each testcase. I'm travelling these days, but I can have a look at idea above later this week and see how viable it is. Regards, Jan > > Regards, > Jan > > ------------------------------------------------------------------------------ > Sponsored by Intel(R) XDK > Develop, test and display web and hybrid apps with a single code base. > Download it for free now! > http://pubads.g.doubleclick.net/gampad/clk?id=111408631&iu=/4140/ostg.clktrk > _______________________________________________ > Ltp-list mailing list > Ltp...@li... > https://lists.sourceforge.net/lists/listinfo/ltp-list > |
From: zenglg.jy <zen...@cn...> - 2013-12-10 08:05:29
|
On Tue, 2013-12-10 at 02:54 -0500, Jan Stancek wrote: > > > > ----- Original Message ----- > > From: "Jan Stancek" <jst...@re...> > > To: "zenglg.jy" <zen...@cn...> > > Cc: "ltp-list" <ltp...@li...> > > Sent: Monday, 9 December, 2013 5:15:32 PM > > Subject: Re: [LTP] [PATCH v3 2/2] clone/clone08.c: Add new flags > > > > > > > > I was running v3 with only "CLONE_THREAD" testcase enabled: > > - {"CLONE_PARENT", CLONE_PARENT | CLONE_VM | SIGCHLD, NULL, > > - child_clone_parent}, > > - {"CLONE_CHILD_SETTID", CLONE_CHILD_SETTID | CLONE_VM | SIGCHLD, NULL, > > - child_clone_child_settid}, > > - {"CLONE_PARENT_SETTID", CLONE_PARENT_SETTID | CLONE_VM | SIGCHLD, > > NULL, > > - child_clone_parent_settid}, > > -#ifdef CLONE_STOPPED > > - {"CLONE_STOPPED", CLONE_STOPPED | CLONE_VM | SIGCHLD, > > - test_clone_stopped, child_clone_stopped}, > > -#endif > > > > and I see it failing/crashing sometimes. I usually see one of these failures: > > > > 1. clone08 4 TBROK : Failed to read from pipe at clone08.c:168: > > errno=EAGAIN(11): Resource temporarily unavailable > > 2. clone08 1 TBROK : The other end of the pipe was closed unexpectedly > > at clone08.c:168 > > 3. clone08 4 TPASS : test CLONE_THREAD success > > clone08 1 TBROK : unexpected signal 11 received (pid = 8234). > > clone08 2 TBROK : Remaining cases broken > > clone08 1 TFAIL : son process exits error > > 4. no error, but test doesn't execute as many times as specified on command > > line > > 5. clone08 1 TBROK : unexpected signal 4 received (pid = 28936). > > Some of above are caused by multiple threads reusing same stack area. > Trouble is that with single master child you can't be sure when > CLONE_THREAD child finished using its stack. > > The idea I mentioned in v2 was basically what you did, but the loop for testcases > would be outside master child - which means spawning master_child for each testcase. > > I'm travelling these days, but I can have a look at idea above later this week > and see how viable it is. > OK, thanks. I am working on it. Best regards, Zeng > Regards, > Jan > > > > > Regards, > > Jan > > > > ------------------------------------------------------------------------------ > > Sponsored by Intel(R) XDK > > Develop, test and display web and hybrid apps with a single code base. > > Download it for free now! > > http://pubads.g.doubleclick.net/gampad/clk?id=111408631&iu=/4140/ostg.clktrk > > _______________________________________________ > > Ltp-list mailing list > > Ltp...@li... > > https://lists.sourceforge.net/lists/listinfo/ltp-list > > |