----- Original Message -----
> From: "zenglg.jy" <[email protected]>
> To: "chrubis" <[email protected]>
> Cc: "ltp-list" <[email protected]>
> 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 <[email protected]>
> ---
> 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 <[email protected]>
> + *
> + * 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
> [email protected]
> https://lists.sourceforge.net/lists/listinfo/ltp-list
>
------------------------------------------------------------------------------
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
[email protected]
https://lists.sourceforge.net/lists/listinfo/ltp-list