[CRIU] [PATCHv2 2/2] test/others/leave-stopped: implement test for new --leave-stopped option

Batalov Eugene eabatalov89 at gmail.com
Fri May 20 07:15:23 PDT 2016


2016-05-20 16:50 GMT+03:00 Pavel Emelyanov <xemul at virtuozzo.com>:

> On 05/20/2016 04:31 PM, Batalov Eugene wrote:
> >
> > 2016-05-20 16:12 GMT+03:00 Pavel Emelyanov <xemul at virtuozzo.com <mailto:
> xemul at virtuozzo.com>>:
> >
> >     On 05/20/2016 02:31 PM, Batalov Eugene wrote:
> >     >
> >     >
> >     > 2016-05-20 14:23 GMT+03:00 Pavel Emelyanov <xemul at virtuozzo.com
> <mailto:xemul at virtuozzo.com> <mailto:xemul at virtuozzo.com <mailto:
> xemul at virtuozzo.com>>>:
> >     >
> >     >     On 05/02/2016 06:46 PM, Eugene Batalov wrote:
> >     >     > From: Kravchenko Dmitrii <equivalence1 at gmail.com <mailto:
> equivalence1 at gmail.com> <mailto:equivalence1 at gmail.com <mailto:
> equivalence1 at gmail.com>>>
> >     >     >
> >     >     > This patch implements a simple autotest for new
> --leave-stopped CRIU
> >     >     > restorer option. Test creates ps tree then checkpoints it.
> >     >     > Then test restores ps tree with --leave-stopped option.
> >     >     > Then test checks that every process in restored ps tree is in
> >     >     > stopped state.
> >     >     >
> >     >     > Signed-off-by: Kravchenko Dmitrii <equivalence1 at gmail.com
> <mailto:equivalence1 at gmail.com> <mailto:equivalence1 at gmail.com <mailto:
> equivalence1 at gmail.com>>>
> >     >     > Signed-off-by: Eugene Batalov <eabatalov89 at gmail.com
> <mailto:eabatalov89 at gmail.com> <mailto:eabatalov89 at gmail.com <mailto:
> eabatalov89 at gmail.com>>>
> >     >     > ---
> >     >     >  test/others/leave-stopped/.gitignore      |  3 ++
> >     >     >  test/others/leave-stopped/Makefile        |  7 +++++
> >     >     >  test/others/leave-stopped/pstree.c        | 39
> +++++++++++++++++++++++++
> >     >     >  test/others/leave-stopped/run.sh          | 31
> ++++++++++++++++++++
> >     >     >  test/others/leave-stopped/tree_checker.py | 47
> +++++++++++++++++++++++++++++++
> >     >
> >     >     Oh :( Is there any chance to have this as a part of zdtm.py
> suite?
> >     >
> >     >
> >     > We need to restore the whole ps tree in stopped state so ps tree
> can't validate itself after restore.
> >
> >     Of course. This should be a mode when zdtm.py passes --leave-stopped
> to criu restore (and
> >     criu dump actually too :) ) and before checking the results SIGCONTs
> the tree.
> >
> > We should check state of all the restored processes in ps tree before we
> SIGCONT them.
> > Please read my comment below for continuation of my point.
> >
> >
> >
> >     > I think there should be some file in CRIU test suite where we can
> add new shell command to run our non-zdtm style test.
> >     > But we haven't found such a file.
> >     > Do you have such a shell script? Should we implement such a file?
> >
> >     Nope :( But this can be solved by calling "crit x ps" -- it will
> show all the pids
> >     from the image file.
> >
> > In our test we traverse restored ps tree from root to children and check
> each process state to be stopped.
> > So I don't see a big need to use additional component such as crit in
> our test (but crit ps based check is more strict).
> >
> > The question is how would we integrate our test/others/leave-stopped
> script into zdtm test suite?
>
> I thought that you don't :) Instead, you can take the zdtm/transition/fork
> test, C/R it
> with --leave-stopped, check that it is stopped, SIGCONT the tree and check
> the result.
>
> The same can be done with any zdtm/ micro-test, but presumably it only
> makes sense to
> regularly test only the fork one.

So will we need some special logic in zdtm.py for running and sigcont of
zdtm/transition/fork test with --leave-stopped flag?
If yes, do you have a similar test with special running logic in zdtm.py
already?

Also is this really needed to use zdtm/transition/fork and integrate
special logic into zdtm.py?
Is there a big deal in it? :) Because it doesn't look like a problem for me
but it would take some extra time.




> > The cleanest way is to just call our test script from zdtm and let our
> test script do all the work.
> > I mean it looks like there is no need to add more code into zdtm.py.
> > It is complicated thing already so I prefer not to add more
> functionality inside it (we have another
> > isolated test and can just run it from zdtm.py).
> >
> >
> >
> >     >
> >     >
> >     >     >  5 files changed, 127 insertions(+)
> >     >     >  create mode 100644 test/others/leave-stopped/.gitignore
> >     >     >  create mode 100644 test/others/leave-stopped/Makefile
> >     >     >  create mode 100644 test/others/leave-stopped/pstree.c
> >     >     >  create mode 100755 test/others/leave-stopped/run.sh
> >     >     >  create mode 100755 test/others/leave-stopped/tree_checker.py
> >     >     >
> >     >     > diff --git a/test/others/leave-stopped/.gitignore
> b/test/others/leave-stopped/.gitignore
> >     >     > new file mode 100644
> >     >     > index 0000000..f0f7d9e
> >     >     > --- /dev/null
> >     >     > +++ b/test/others/leave-stopped/.gitignore
> >     >     > @@ -0,0 +1,3 @@
> >     >     > +dump/*
> >     >     > +nohup.out
> >     >     > +pstree
> >     >     > diff --git a/test/others/leave-stopped/Makefile
> b/test/others/leave-stopped/Makefile
> >     >     > new file mode 100644
> >     >     > index 0000000..83e91cc
> >     >     > --- /dev/null
> >     >     > +++ b/test/others/leave-stopped/Makefile
> >     >     > @@ -0,0 +1,7 @@
> >     >     > +pstree: pstree.c
> >     >     > +     gcc -pthread -std=c99 $< -o $@
> >     >     > +
> >     >     > +clean:
> >     >     > +     rm -f pstree
> >     >     > +
> >     >     > +.PHONY: clean
> >     >     > diff --git a/test/others/leave-stopped/pstree.c
> b/test/others/leave-stopped/pstree.c
> >     >     > new file mode 100644
> >     >     > index 0000000..a6e437c
> >     >     > --- /dev/null
> >     >     > +++ b/test/others/leave-stopped/pstree.c
> >     >     > @@ -0,0 +1,39 @@
> >     >     > +#include <stdlib.h>
> >     >     > +#include <unistd.h>
> >     >     > +#include <limits.h>
> >     >     > +#include <pthread.h>
> >     >     > +
> >     >     > +const size_t THREADS_N = 3;
> >     >     > +const size_t TREE_HEIGHT = 3;
> >     >     > +
> >     >     > +static void *hang(void *arg)
> >     >     > +{
> >     >     > +     (void)arg;
> >     >     > +     while (1)
> >     >     > +             sleep(UINT_MAX);
> >     >     > +}
> >     >     > +
> >     >     > +static void create_threads(void)
> >     >     > +{
> >     >     > +     pthread_t thread;
> >     >     > +
> >     >     > +     for (size_t i = 1; i < THREADS_N; i++)
> >     >     > +             pthread_create(&thread, NULL, hang, NULL);
> >     >     > +}
> >     >     > +
> >     >     > +int main(void)
> >     >     > +{
> >     >     > +     /**
> >     >     > +      * just building full binary tree of processes
> >     >     > +      */
> >     >     > +     for (size_t i = 1; i < TREE_HEIGHT; i++) {
> >     >     > +             if (fork()) {
> >     >     > +                     if (fork())
> >     >     > +                             break;
> >     >     > +             }
> >     >     > +     }
> >     >     > +
> >     >     > +     create_threads();
> >     >     > +
> >     >     > +     hang(NULL);
> >     >     > +}
> >     >     > diff --git a/test/others/leave-stopped/run.sh
> b/test/others/leave-stopped/run.sh
> >     >     > new file mode 100755
> >     >     > index 0000000..d2f2ec6
> >     >     > --- /dev/null
> >     >     > +++ b/test/others/leave-stopped/run.sh
> >     >     > @@ -0,0 +1,31 @@
> >     >     > +#!/bin/bash
> >     >     > +
> >     >     > +source ../env.sh || exit 1
> >     >     > +
> >     >     > +make || { echo "Failed to build"; exit 1; }
> >     >     > +
> >     >     > +DDIR="dump"
> >     >     > +
> >     >     > +rm -f nohup.out
> >     >     > +rm -rf ${DDIR}
> >     >     > +
> >     >     > +mkdir ${DDIR}
> >     >     > +
> >     >     > +setsid nohup ./pstree &
> >     >     > +root_pid=$!
> >     >     > +
> >     >     > +${CRIU} dump -D ${DDIR} -t ${root_pid} || \
> >     >     > +     { echo "Failed to dump"; kill -9 -${root_pid}; exit 1;
> }
> >     >     > +${CRIU} restore -D ${DDIR} --leave-stopped -d || \
> >     >     > +     { echo "Failed to restore"; exit 1; }
> >     >     > +
> >     >     > +./tree_checker.py ${root_pid}
> >     >     > +
> >     >     > +if [ $? -eq 0 ]; then
> >     >     > +     echo "PASS"
> >     >     > +     kill -9 -${root_pid}
> >     >     > +else
> >     >     > +     echo "FAIL"
> >     >     > +     kill -9 -${root_pid}
> >     >     > +     exit 1
> >     >     > +fi
> >     >     > diff --git a/test/others/leave-stopped/tree_checker.py
> b/test/others/leave-stopped/tree_checker.py
> >     >     > new file mode 100755
> >     >     > index 0000000..87d45e2
> >     >     > --- /dev/null
> >     >     > +++ b/test/others/leave-stopped/tree_checker.py
> >     >     > @@ -0,0 +1,47 @@
> >     >     > +#!/usr/bin/python2
> >     >     > +
> >     >     > +import os
> >     >     > +import sys
> >     >     > +
> >     >     > +
> >     >     > +def get_thread_status(thread_dir):
> >     >     > +     for line in open(os.path.join(thread_dir,
> "status")).readlines():
> >     >     > +             if line.startswith("State:"):
> >     >     > +                     return line.split(":",
> 1)[1].strip().split(' ')[0]
> >     >     > +     return None
> >     >     > +
> >     >     > +
> >     >     > +def is_process_stopped(pid):
> >     >     > +     tasks_dir = "/proc/{}/task".format(pid)
> >     >     > +
> >     >     > +     for thread_dir in os.listdir(tasks_dir):
> >     >     > +             thread_status =
> get_thread_status(os.path.join(tasks_dir, thread_dir))
> >     >     > +             if not thread_status == "T":
> >     >     > +                     return False
> >     >     > +
> >     >     > +     thread_status =
> get_thread_status("/proc/{}".format(pid))
> >     >     > +     if not thread_status == "T":
> >     >     > +             return False
> >     >     > +
> >     >     > +     return True
> >     >     > +
> >     >     > +
> >     >     > +def check_tree(root_pid):
> >     >     > +     if not is_process_stopped(root_pid):
> >     >     > +             print "Process with pid {} is not
> stopped.".format(root_pid)
> >     >     > +             return False
> >     >     > +
> >     >     > +     f_children_path =
> "/proc/{0}/task/{0}/children".format(root_pid)
> >     >     > +
> >     >     > +     with open(f_children_path, "r") as f_children:
> >     >     > +             for line in f_children:
> >     >     > +                     for child_pid in line.strip().split("
> "):
> >     >     > +                             if not
> check_tree(int(child_pid)):
> >     >     > +                                     return False
> >     >     > +
> >     >     > +     return True
> >     >     > +
> >     >     > +
> >     >     > +if __name__ == "__main__":
> >     >     > +     if not check_tree(sys.argv[1]):
> >     >     > +             sys.exit(1)
> >     >     >
> >     >
> >     >
> >     >
> >     >
> >     > --
> >     > Best regards,
> >     > Eugene Batalov.
> >
> >
> >
> >
> > --
> > Best regards,
> > Eugene Batalov.
>
>


-- 
Best regards,
Eugene Batalov.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.openvz.org/pipermail/criu/attachments/20160520/5d5edb0e/attachment-0001.html>


More information about the CRIU mailing list