diff --git a/test/zdtm.sh b/test/zdtm.sh index edb3c11ea..ffc8504fb 100644 --- a/test/zdtm.sh +++ b/test/zdtm.sh @@ -28,6 +28,9 @@ $ZP/static/zombie00 $ZP/static/cmdlinenv00 $ZP/static/socket_listen" +NS_TEST_LIST="\ +$ZP/static/utsname" + CRTOOLS=`pwd`/`dirname $0`/../crtools run_test() @@ -43,13 +46,13 @@ run_test() dump_path=`pwd`"/"$ddump mkdir -p $ddump ls -l /proc/$pid/fd/ - setsid $CRTOOLS dump -D $ddump -o dump.log -t $pid || return 1 + setsid $CRTOOLS dump -D $ddump -o dump.log -t $pid $2 || return 1 while :; do killall -9 $tname &> /dev/null || break; echo Waiting... sleep 1 done - setsid $CRTOOLS restore -D $ddump -o restore.log -d -t $pid || return 2 + setsid $CRTOOLS restore -D $ddump -o restore.log -d -t $pid $2 || return 2 ls -l /proc/$pid/fd/ make -C $tdir $tname.out for i in `seq 50`; do @@ -65,12 +68,20 @@ cd `dirname $0` || exit 1 if [ $# -eq 0 ]; then for t in $TEST_LIST; do - run_test $t || exit 1 + run_test $t "" || exit 1 + done + for t in $NS_TEST_LIST; do + run_test $t "-n" || exit 1 done elif [ "$1" == "-l" ]; then echo $TEST_LIST | sed -e "s#$ZP/##g" -e 's/ /\n/g' + echo $NS_TEST_LIST | sed -e "s#$ZP/##g" -e 's/ /\n/g' else - run_test $ZP/$1 && exit 0 + if echo "$NS_TEST_LIST" | fgrep -q "$1" ; then + run_test "$ZP/$1" "-n" && exit 0 + else + run_test "$ZP/$1" && exit 0 + fi result=$? echo "====================== ERROR ======================" if [ $result == 1 ]; then diff --git a/test/zdtm/lib/test.c b/test/zdtm/lib/test.c index ae023305c..d5acef8df 100644 --- a/test/zdtm/lib/test.c +++ b/test/zdtm/lib/test.c @@ -7,6 +7,7 @@ #include #include #include +#include #include "zdtmtst.h" @@ -153,6 +154,113 @@ void test_init(int argc, char **argv) srand48(time(NULL)); /* just in case we need it */ } +#define STACK_SIZE (8 * 4096) + +struct zdtm_clone_arg { + int pidf; + void (*fn)(void); +}; + +static int do_test_fn(void *_arg) +{ + struct zdtm_clone_arg *ca = _arg; + struct sigaction sa; + + /* record the test pid to remember the ownership of the pidfile */ + master_pid = getpid(); + + fclose(ca->pidf); + + sigemptyset(&sa.sa_mask); + sa.sa_handler = SIG_DFL; + if (sigaction(SIGCHLD, &sa, NULL)) { + err("Can't reset SIGCHLD handler: %m\n"); + exit(1); + } + + if (setsid() < 0) { + err("Can't become session group leader: %m\n"); + exit(1); + } + + srand48(time(NULL)); /* just in case we need it */ + + ca->fn(); + exit(0); +} + +void test_init_ns(int argc, char **argv, unsigned long clone_flags, void (*fn)(void)) +{ + extern void parseargs(int, char **); + + pid_t pid; + static FILE *pidf; + struct sigaction sa = { + .sa_handler = sig_hand, + }; + struct zdtm_clone_arg ca; + void *stack; + + sigemptyset(&sa.sa_mask); + + if (sigaction(SIGTERM, &sa, NULL)) { + fprintf(stderr, "Can't set SIGTERM handler: %m\n"); + exit(1); + } + + if (sigaction(SIGCHLD, &sa, NULL)) { + fprintf(stderr, "Can't set SIGCHLD handler: %m\n"); + exit(1); + } + + parseargs(argc, argv); + + setup_outfile(); + redir_stdfds(); + + pidf = fopen(pidfile, "wx"); + if (!pidf) { + err("Can't create pid file %s: %m\n", pidfile); + exit(1); + } + + stack = mmap(NULL, STACK_SIZE, PROT_WRITE | PROT_READ, + MAP_PRIVATE | MAP_GROWSDOWN | MAP_ANONYMOUS, -1, 0); + if (stack == MAP_FAILED) { + err("Can't map stack\n"); + exit(1); + } + + ca.pidf = pidf; + ca.fn = fn; + pid = clone(do_test_fn, stack + STACK_SIZE, clone_flags | SIGCHLD, &ca); + if (pid < 0) { + err("Daemonizing failed: %m\n"); + exit(1); + } + + /* parent will exit when the child is ready */ + test_waitsig(); + + if (sig_received == SIGCHLD) { + int ret; + waitpid(pid, &ret, 0); + + if (WIFEXITED(ret)) { + err("Test exited with unexpectedly with code %d\n", WEXITSTATUS(ret)); + exit(0); + } + if (WIFSIGNALED(ret)) { + err("Test exited on unexpected signal %d\n", WTERMSIG(ret)); + exit(0); + } + } + + fprintf(pidf, "%d\n", pid); + fclose(pidf); + _exit(0); +} + void test_daemon() { pid_t ppid; diff --git a/test/zdtm/lib/zdtmtst.h b/test/zdtm/lib/zdtmtst.h index 4049f1d57..fe329b01b 100644 --- a/test/zdtm/lib/zdtmtst.h +++ b/test/zdtm/lib/zdtmtst.h @@ -5,6 +5,12 @@ /* set up test */ extern void test_init(int argc, char **argv); +extern void test_init_ns(int argc, char **argv, unsigned long clone_flags, void (*fn)(void)); + +#ifndef CLONE_NEWUTS +#define CLONE_NEWUTS 0x04000000 +#endif + /*wrapper for fork: init log offset*/ extern int test_fork(); /* finish setting up the test, write out pid file, and go to background */ diff --git a/test/zdtm/live/static/Makefile b/test/zdtm/live/static/Makefile index 433c968e9..7fb1affaa 100644 --- a/test/zdtm/live/static/Makefile +++ b/test/zdtm/live/static/Makefile @@ -28,6 +28,7 @@ TST_NOFILE = \ pthread00 \ vdso00 \ cmdlinenv00 \ + utsname \ # jobctl00 \ TST_FILE = \