[CRIU] [PATCH] zdtm: add a small program to create a zdtm container

Andrew Vagin avagin at parallels.com
Tue Aug 12 12:17:22 PDT 2014


On Tue, Aug 12, 2014 at 02:34:20PM -0400, Christopher Covington wrote:
> Hi Andrey
> 
> On 08/12/2014 12:13 PM, Andrey Vagin wrote:
> > I didn't find a way how to do that with help "unshare".
> > It's simpler to write this program. It looks better than tricks in
> > zdtm.sh.
> 
> How different is this from `criu restore -n mnt,pid,net,ipc`?

I don't understand the question. This program is used to execute zdtm.sh
in a container to avoid races between tests.
The most popular race condition is when one test takes PID of another
test, and the second test can't be restored.

You could try to remove the --ct options from test/Makefile and execute:
$ make -j 4 zdtm_nons
[root at avagin-fc19-cr criu]# make -C test/ -j 4 zdtm_nons
make: Entering directory `/root/git/orig/criu/test'
./zdtm.sh -C static/pipe00 &> static_pipe00.log || \
{ flock Makefile cat static_pipe00.log; exit 1; }
./zdtm.sh -C static/pipe01 &> static_pipe01.log || \
{ flock Makefile cat static_pipe01.log; exit 1; }
./zdtm.sh -C static/pipe02 &> static_pipe02.log || \
{ flock Makefile cat static_pipe02.log; exit 1; }
./zdtm.sh -C static/busyloop00 &> static_busyloop00.log || \
{ flock Makefile cat static_busyloop00.log; exit 1; }
================================= CRIU CHECK =================================
Looks good.
Execute zdtm/live/static/pipe02
./pipe02 --pidfile=pipe02.pid --outfile=pipe02.out
Dump 8328
Restore
Test: zdtm/live/static/pipe02, Result: FAIL
==================================== ERROR ====================================
Test: zdtm/live/static/pipe02, Namespace: 
Dump log   : /root/git/orig/criu/test/dump/static/pipe02/8328/1/dump.log
--------------------------------- grep Error ---------------------------------
------------------------------------- END -------------------------------------
Restore log: /root/git/orig/criu/test/dump/static/pipe02/8328/1/restore.log
--------------------------------- grep Error ---------------------------------
(00.002222) Error (cr-restore.c:1324): Pid 8329 do not match expected 8328
(00.003502) Error (cr-restore.c:1083): 8329 exited, status=255
(00.003565) Error (cr-restore.c:1702): Restoring FAILED.
------------------------------------- END -------------------------------------
================================= ERROR OVER =================================

make: *** [static/pipe02] Error 1
make: *** Waiting for unfinished jobs....
make: Leaving directory `/root/git/orig/criu/test'

We can workaround this race, if we will execute all tests in own pid namespaces.

Maybe you mean that a test can be restored in a new pid namespace.
Currently criu can't do that. Here is a few questions. Who will be
the init process? The root task probably doesn't ready to be a sub-reaper.
Do we need to remount /proc? If the answer is yes, we need to create
a new mount namespace together with pidns.
I think this is interesting task, which will be one day implemented.

Thanks.


> 
> Thanks,
> Christopher
> 
> > diff --git a/test/.gitignore b/test/.gitignore
> > index 9f00af7..1a6f6d2 100644
> > --- a/test/.gitignore
> > +++ b/test/.gitignore
> > @@ -4,3 +4,4 @@
> >  /dev
> >  /dump
> >  /*.log
> > +/zdtm_ct
> > diff --git a/test/Makefile b/test/Makefile
> > index 5d04805..fdb96ee 100644
> > --- a/test/Makefile
> > +++ b/test/Makefile
> > @@ -28,6 +28,12 @@ fault-injection: .FORCE
> >  zdtm_ns: $(shell echo "$(TST)" | tr ' ' '\n' | grep -P $(EXP))
> >  zdtm_nons: $(shell echo "$(TST)" | tr ' ' '\n' | grep -vP $(EXP))
> >  
> > +zdtm_ct: zdtm_ct.c
> > +
> > +clean:
> > +	rm -rf zdtm_ct
> > +	$(MAKE) -C zdtm $@
> > +
> >  $(TST):
> >  	./zdtm.sh --ct ${ZDTM_ARGS} $(@) &> $(subst /,_,$@).log || \
> >  	{ flock Makefile cat $(subst /,_,$@).log; exit 1; }
> > diff --git a/test/zdtm.sh b/test/zdtm.sh
> > index 395b256..2064866 100755
> > --- a/test/zdtm.sh
> > +++ b/test/zdtm.sh
> > @@ -874,21 +874,11 @@ while :; do
> >  		[ -z "$ZDTM_SH_IN_CT" ] && {
> >  			export ZDTM_SH_IN_CT=1
> >  			shift
> > -			args="$@"
> >  			# pidns is used to avoid conflicts
> >  			# mntns is used to mount /proc
> >  			# net is used to avoid conflicts of parasite sockets
> > -			unshare --pid --mount --ipc --net -- bash -c "
> > -				(
> > -					ip link set up dev lo &&
> > -					mount --make-rprivate / &&
> > -					umount -l /proc &&
> > -					mount -t proc proc /proc/ &&
> > -					umount -l /dev/pts &&
> > -					mount -t devpts zdtm_pts /dev/pts -o newinstance,ptmxmode=666 &&
> > -					mount --bind /dev/pts/ptmx /dev/ptmx &&
> > -					./zdtm.sh $args
> > -				)"
> > +			make zdtm_ct &&
> > +			./zdtm_ct ./zdtm.sh "$@"
> >  			exit
> >  		}
> >  		shift
> > diff --git a/test/zdtm_ct.c b/test/zdtm_ct.c
> > new file mode 100644
> > index 0000000..e3e9508
> > --- /dev/null
> > +++ b/test/zdtm_ct.c
> > @@ -0,0 +1,55 @@
> > +#define _GNU_SOURCE
> > +#include <sched.h>
> > +#include <sys/types.h>
> > +#include <sys/wait.h>
> > +#include <stdlib.h>
> > +#include <stdio.h>
> > +#include <sys/mount.h>
> > +
> > +int main(int argc, char **argv)
> > +{
> > +	pid_t pid;
> > +	int status;
> > +
> > +	/*
> > +	 *pidns is used to avoid conflicts
> > +	 * mntns is used to mount /proc
> > +	 * net is used to avoid conflicts of parasite sockets
> > +	*/
> > +	if (unshare(CLONE_NEWNS | CLONE_NEWPID | CLONE_NEWNET | CLONE_NEWIPC))
> > +		return 1;
> > +	pid = fork();
> > +	if (pid == 0) {
> > +		if (mount(NULL, "/", NULL, MS_REC | MS_PRIVATE, NULL)) {
> > +			fprintf(stderr, "mount(/, S_REC | MS_PRIVATE)): %m");
> > +			return 1;
> > +		}
> > +		umount2("/proc", MNT_DETACH);
> > +		umount2("/dev/pts", MNT_DETACH);
> > +		if (mount("zdtm_proc", "/proc", "proc", 0, NULL)) {
> > +			fprintf(stderr, "mount(/proc): %m");
> > +			return 1;
> > +		}
> > +		if (mount("zdtm_devpts", "/dev/pts", "devpts", 0,
> > +					"newinstance,ptmxmode=0666")) {
> > +			fprintf(stderr, "mount(pts): %m");
> > +			return 1;
> > +		}
> > +		if (mount("/dev/pts/ptmx", "/dev/ptmx", NULL, MS_BIND, NULL)) {
> > +			fprintf(stderr, "mount(ptmx): %m");
> > +			return 1;
> > +		}
> > +		if (system("ip link set up dev lo"))
> > +			return 1;
> > +		execv(argv[1], argv + 1);
> > +		fprintf(stderr, "execve: %m");
> > +		return 1;
> > +	}
> > +
> > +	if (wait(&status) < 0) {
> > +		fprintf(stderr, "wait: %m");
> > +		return 1;
> > +	}
> > +
> > +	return status != 0 ? 1 : 0;
> > +}
> > 
> 
> 
> -- 
> Employee of Qualcomm Innovation Center, Inc.
> Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
> hosted by the Linux Foundation.


More information about the CRIU mailing list