<div dir="ltr"><div class="gmail_extra"><br><div class="gmail_quote">2016-05-20 16:12 GMT+03:00 Pavel Emelyanov <span dir="ltr">&lt;<a href="mailto:xemul@virtuozzo.com" target="_blank">xemul@virtuozzo.com</a>&gt;</span>:<br><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">On 05/20/2016 02:31 PM, Batalov Eugene wrote:<br>
&gt;<br>
&gt;<br>
&gt; 2016-05-20 14:23 GMT+03:00 Pavel Emelyanov &lt;<a href="mailto:xemul@virtuozzo.com">xemul@virtuozzo.com</a> &lt;mailto:<a href="mailto:xemul@virtuozzo.com">xemul@virtuozzo.com</a>&gt;&gt;:<br>
<span class="">&gt;<br>
&gt;     On 05/02/2016 06:46 PM, Eugene Batalov wrote:<br>
</span>&gt;     &gt; From: Kravchenko Dmitrii &lt;<a href="mailto:equivalence1@gmail.com">equivalence1@gmail.com</a> &lt;mailto:<a href="mailto:equivalence1@gmail.com">equivalence1@gmail.com</a>&gt;&gt;<br>
<span class="">&gt;     &gt;<br>
&gt;     &gt; This patch implements a simple autotest for new --leave-stopped CRIU<br>
&gt;     &gt; restorer option. Test creates ps tree then checkpoints it.<br>
&gt;     &gt; Then test restores ps tree with --leave-stopped option.<br>
&gt;     &gt; Then test checks that every process in restored ps tree is in<br>
&gt;     &gt; stopped state.<br>
&gt;     &gt;<br>
</span>&gt;     &gt; Signed-off-by: Kravchenko Dmitrii &lt;<a href="mailto:equivalence1@gmail.com">equivalence1@gmail.com</a> &lt;mailto:<a href="mailto:equivalence1@gmail.com">equivalence1@gmail.com</a>&gt;&gt;<br>
&gt;     &gt; Signed-off-by: Eugene Batalov &lt;<a href="mailto:eabatalov89@gmail.com">eabatalov89@gmail.com</a> &lt;mailto:<a href="mailto:eabatalov89@gmail.com">eabatalov89@gmail.com</a>&gt;&gt;<br>
<span class="">&gt;     &gt; ---<br>
&gt;     &gt;  test/others/leave-stopped/.gitignore      |  3 ++<br>
&gt;     &gt;  test/others/leave-stopped/Makefile        |  7 +++++<br>
&gt;     &gt;  test/others/leave-stopped/pstree.c        | 39 +++++++++++++++++++++++++<br>
&gt;     &gt;  test/others/leave-stopped/run.sh          | 31 ++++++++++++++++++++<br>
&gt;     &gt;  test/others/leave-stopped/tree_checker.py | 47 +++++++++++++++++++++++++++++++<br>
&gt;<br>
&gt;     Oh :( Is there any chance to have this as a part of zdtm.py suite?<br>
&gt;<br>
&gt;<br>
&gt; We need to restore the whole ps tree in stopped state so ps tree can&#39;t validate itself after restore.<br>
<br>
</span>Of course. This should be a mode when zdtm.py passes --leave-stopped to criu restore (and<br>
criu dump actually too :) ) and before checking the results SIGCONTs the tree.<br></blockquote><div>We should check state of all the restored processes in ps tree before we SIGCONT them.</div><div>Please read my comment below for continuation of my point.</div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">
<span class=""><br>
&gt; 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.<br>
&gt; But we haven&#39;t found such a file.<br>
&gt; Do you have such a shell script? Should we implement such a file?<br>
<br>
</span>Nope :( But this can be solved by calling &quot;crit x ps&quot; -- it will show all the pids<br>
from the image file.<br></blockquote><div>In our test we traverse restored ps tree from root to children and check each process state to be stopped.</div><div>So I don&#39;t see a big need to use additional component such as crit in our test (but crit ps based check is more strict).</div><div><br></div><div>The question is how would we integrate our test/others/leave-stopped script into zdtm test suite?</div><div>The cleanest way is to just call our test script from zdtm and let our test script do all the work.</div><div>I mean it looks like there is no need to add more code into zdtm.py.</div><div>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).</div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">
<div class=""><div class="h5"><br>
&gt;<br>
&gt;<br>
&gt;     &gt;  5 files changed, 127 insertions(+)<br>
&gt;     &gt;  create mode 100644 test/others/leave-stopped/.gitignore<br>
&gt;     &gt;  create mode 100644 test/others/leave-stopped/Makefile<br>
&gt;     &gt;  create mode 100644 test/others/leave-stopped/pstree.c<br>
&gt;     &gt;  create mode 100755 test/others/leave-stopped/run.sh<br>
&gt;     &gt;  create mode 100755 test/others/leave-stopped/tree_checker.py<br>
&gt;     &gt;<br>
&gt;     &gt; diff --git a/test/others/leave-stopped/.gitignore b/test/others/leave-stopped/.gitignore<br>
&gt;     &gt; new file mode 100644<br>
&gt;     &gt; index 0000000..f0f7d9e<br>
&gt;     &gt; --- /dev/null<br>
&gt;     &gt; +++ b/test/others/leave-stopped/.gitignore<br>
&gt;     &gt; @@ -0,0 +1,3 @@<br>
&gt;     &gt; +dump/*<br>
&gt;     &gt; +nohup.out<br>
&gt;     &gt; +pstree<br>
&gt;     &gt; diff --git a/test/others/leave-stopped/Makefile b/test/others/leave-stopped/Makefile<br>
&gt;     &gt; new file mode 100644<br>
&gt;     &gt; index 0000000..83e91cc<br>
&gt;     &gt; --- /dev/null<br>
&gt;     &gt; +++ b/test/others/leave-stopped/Makefile<br>
&gt;     &gt; @@ -0,0 +1,7 @@<br>
&gt;     &gt; +pstree: pstree.c<br>
&gt;     &gt; +     gcc -pthread -std=c99 $&lt; -o $@<br>
&gt;     &gt; +<br>
&gt;     &gt; +clean:<br>
&gt;     &gt; +     rm -f pstree<br>
&gt;     &gt; +<br>
&gt;     &gt; +.PHONY: clean<br>
&gt;     &gt; diff --git a/test/others/leave-stopped/pstree.c b/test/others/leave-stopped/pstree.c<br>
&gt;     &gt; new file mode 100644<br>
&gt;     &gt; index 0000000..a6e437c<br>
&gt;     &gt; --- /dev/null<br>
&gt;     &gt; +++ b/test/others/leave-stopped/pstree.c<br>
&gt;     &gt; @@ -0,0 +1,39 @@<br>
&gt;     &gt; +#include &lt;stdlib.h&gt;<br>
&gt;     &gt; +#include &lt;unistd.h&gt;<br>
&gt;     &gt; +#include &lt;limits.h&gt;<br>
&gt;     &gt; +#include &lt;pthread.h&gt;<br>
&gt;     &gt; +<br>
&gt;     &gt; +const size_t THREADS_N = 3;<br>
&gt;     &gt; +const size_t TREE_HEIGHT = 3;<br>
&gt;     &gt; +<br>
&gt;     &gt; +static void *hang(void *arg)<br>
&gt;     &gt; +{<br>
&gt;     &gt; +     (void)arg;<br>
&gt;     &gt; +     while (1)<br>
&gt;     &gt; +             sleep(UINT_MAX);<br>
&gt;     &gt; +}<br>
&gt;     &gt; +<br>
&gt;     &gt; +static void create_threads(void)<br>
&gt;     &gt; +{<br>
&gt;     &gt; +     pthread_t thread;<br>
&gt;     &gt; +<br>
&gt;     &gt; +     for (size_t i = 1; i &lt; THREADS_N; i++)<br>
&gt;     &gt; +             pthread_create(&amp;thread, NULL, hang, NULL);<br>
&gt;     &gt; +}<br>
&gt;     &gt; +<br>
&gt;     &gt; +int main(void)<br>
&gt;     &gt; +{<br>
&gt;     &gt; +     /**<br>
&gt;     &gt; +      * just building full binary tree of processes<br>
&gt;     &gt; +      */<br>
&gt;     &gt; +     for (size_t i = 1; i &lt; TREE_HEIGHT; i++) {<br>
&gt;     &gt; +             if (fork()) {<br>
&gt;     &gt; +                     if (fork())<br>
&gt;     &gt; +                             break;<br>
&gt;     &gt; +             }<br>
&gt;     &gt; +     }<br>
&gt;     &gt; +<br>
&gt;     &gt; +     create_threads();<br>
&gt;     &gt; +<br>
&gt;     &gt; +     hang(NULL);<br>
&gt;     &gt; +}<br>
&gt;     &gt; diff --git a/test/others/leave-stopped/run.sh b/test/others/leave-stopped/run.sh<br>
&gt;     &gt; new file mode 100755<br>
&gt;     &gt; index 0000000..d2f2ec6<br>
&gt;     &gt; --- /dev/null<br>
&gt;     &gt; +++ b/test/others/leave-stopped/run.sh<br>
&gt;     &gt; @@ -0,0 +1,31 @@<br>
&gt;     &gt; +#!/bin/bash<br>
&gt;     &gt; +<br>
&gt;     &gt; +source ../env.sh || exit 1<br>
&gt;     &gt; +<br>
&gt;     &gt; +make || { echo &quot;Failed to build&quot;; exit 1; }<br>
&gt;     &gt; +<br>
&gt;     &gt; +DDIR=&quot;dump&quot;<br>
&gt;     &gt; +<br>
&gt;     &gt; +rm -f nohup.out<br>
&gt;     &gt; +rm -rf ${DDIR}<br>
&gt;     &gt; +<br>
&gt;     &gt; +mkdir ${DDIR}<br>
&gt;     &gt; +<br>
&gt;     &gt; +setsid nohup ./pstree &amp;<br>
&gt;     &gt; +root_pid=$!<br>
&gt;     &gt; +<br>
&gt;     &gt; +${CRIU} dump -D ${DDIR} -t ${root_pid} || \<br>
&gt;     &gt; +     { echo &quot;Failed to dump&quot;; kill -9 -${root_pid}; exit 1; }<br>
&gt;     &gt; +${CRIU} restore -D ${DDIR} --leave-stopped -d || \<br>
&gt;     &gt; +     { echo &quot;Failed to restore&quot;; exit 1; }<br>
&gt;     &gt; +<br>
&gt;     &gt; +./tree_checker.py ${root_pid}<br>
&gt;     &gt; +<br>
&gt;     &gt; +if [ $? -eq 0 ]; then<br>
&gt;     &gt; +     echo &quot;PASS&quot;<br>
&gt;     &gt; +     kill -9 -${root_pid}<br>
&gt;     &gt; +else<br>
&gt;     &gt; +     echo &quot;FAIL&quot;<br>
&gt;     &gt; +     kill -9 -${root_pid}<br>
&gt;     &gt; +     exit 1<br>
&gt;     &gt; +fi<br>
&gt;     &gt; diff --git a/test/others/leave-stopped/tree_checker.py b/test/others/leave-stopped/tree_checker.py<br>
&gt;     &gt; new file mode 100755<br>
&gt;     &gt; index 0000000..87d45e2<br>
&gt;     &gt; --- /dev/null<br>
&gt;     &gt; +++ b/test/others/leave-stopped/tree_checker.py<br>
&gt;     &gt; @@ -0,0 +1,47 @@<br>
&gt;     &gt; +#!/usr/bin/python2<br>
&gt;     &gt; +<br>
&gt;     &gt; +import os<br>
&gt;     &gt; +import sys<br>
&gt;     &gt; +<br>
&gt;     &gt; +<br>
&gt;     &gt; +def get_thread_status(thread_dir):<br>
&gt;     &gt; +     for line in open(os.path.join(thread_dir, &quot;status&quot;)).readlines():<br>
&gt;     &gt; +             if line.startswith(&quot;State:&quot;):<br>
&gt;     &gt; +                     return line.split(&quot;:&quot;, 1)[1].strip().split(&#39; &#39;)[0]<br>
&gt;     &gt; +     return None<br>
&gt;     &gt; +<br>
&gt;     &gt; +<br>
&gt;     &gt; +def is_process_stopped(pid):<br>
&gt;     &gt; +     tasks_dir = &quot;/proc/{}/task&quot;.format(pid)<br>
&gt;     &gt; +<br>
&gt;     &gt; +     for thread_dir in os.listdir(tasks_dir):<br>
&gt;     &gt; +             thread_status = get_thread_status(os.path.join(tasks_dir, thread_dir))<br>
&gt;     &gt; +             if not thread_status == &quot;T&quot;:<br>
&gt;     &gt; +                     return False<br>
&gt;     &gt; +<br>
&gt;     &gt; +     thread_status = get_thread_status(&quot;/proc/{}&quot;.format(pid))<br>
&gt;     &gt; +     if not thread_status == &quot;T&quot;:<br>
&gt;     &gt; +             return False<br>
&gt;     &gt; +<br>
&gt;     &gt; +     return True<br>
&gt;     &gt; +<br>
&gt;     &gt; +<br>
&gt;     &gt; +def check_tree(root_pid):<br>
&gt;     &gt; +     if not is_process_stopped(root_pid):<br>
&gt;     &gt; +             print &quot;Process with pid {} is not stopped.&quot;.format(root_pid)<br>
&gt;     &gt; +             return False<br>
&gt;     &gt; +<br>
&gt;     &gt; +     f_children_path = &quot;/proc/{0}/task/{0}/children&quot;.format(root_pid)<br>
&gt;     &gt; +<br>
&gt;     &gt; +     with open(f_children_path, &quot;r&quot;) as f_children:<br>
&gt;     &gt; +             for line in f_children:<br>
&gt;     &gt; +                     for child_pid in line.strip().split(&quot; &quot;):<br>
&gt;     &gt; +                             if not check_tree(int(child_pid)):<br>
&gt;     &gt; +                                     return False<br>
&gt;     &gt; +<br>
&gt;     &gt; +     return True<br>
&gt;     &gt; +<br>
&gt;     &gt; +<br>
&gt;     &gt; +if __name__ == &quot;__main__&quot;:<br>
&gt;     &gt; +     if not check_tree(sys.argv[1]):<br>
&gt;     &gt; +             sys.exit(1)<br>
&gt;     &gt;<br>
&gt;<br>
&gt;<br>
&gt;<br>
&gt;<br>
&gt; --<br>
&gt; Best regards,<br>
&gt; Eugene Batalov.<br>
<br>
</div></div></blockquote></div><br><br clear="all"><div><br></div>-- <br><div class="gmail_signature">Best regards,<br>Eugene Batalov.</div>
</div></div>