[CRIU] [PATCH cr 01/10] zdtm: add new test case for checking that SID is restored

Andrey Vagin avagin at openvz.org
Tue Jun 19 08:46:52 EDT 2012


    2     2 session00
    4     4  \_ session00		# {NEWSID, },
    2     5  \_ session00		# {0, },
    8     8  \_ session00
    2     9  |   \_ session00           # {CHANGESID, }
   10    10  \_ session00
   11    11      \_ session00
    2    12          \_ session00	# {DOUBLE_CHANGESID | CHANGESID, }
    2     3 session00			# {DETACH, },
    6     7 session00			# {DETACH|NEWSID, },

Signed-off-by: Andrey Vagin <avagin at openvz.org>
---
 test/zdtm.sh                      |    5 +
 test/zdtm/live/static/Makefile    |    1 +
 test/zdtm/live/static/session00.c |  228 +++++++++++++++++++++++++++++++++++++
 3 files changed, 234 insertions(+), 0 deletions(-)
 create mode 100644 test/zdtm/live/static/session00.c

diff --git a/test/zdtm.sh b/test/zdtm.sh
index 2f5cd3e..7f55ff5 100644
--- a/test/zdtm.sh
+++ b/test/zdtm.sh
@@ -53,6 +53,11 @@ transition/fork
 static/file_fown
 "
 
+# These ones are in pidns
+TEST_LIST=$TEST_LIST "
+pidns/static/session00
+"
+
 UTS_TEST_LIST="
 static/utsname
 "
diff --git a/test/zdtm/live/static/Makefile b/test/zdtm/live/static/Makefile
index 3c250ec..d14346d 100644
--- a/test/zdtm/live/static/Makefile
+++ b/test/zdtm/live/static/Makefile
@@ -47,6 +47,7 @@ TST_NOFILE	=				\
 		file_fown			\
 		eventfs00			\
 		inotify00			\
+		session00			\
 #		jobctl00			\
 
 TST_FILE	=				\
diff --git a/test/zdtm/live/static/session00.c b/test/zdtm/live/static/session00.c
new file mode 100644
index 0000000..ef064b9
--- /dev/null
+++ b/test/zdtm/live/static/session00.c
@@ -0,0 +1,228 @@
+#include <unistd.h>
+#include <stdlib.h>
+#include <sys/wait.h>
+
+#include "zdtmtst.h"
+
+const char *test_doc	= "Test that sid, pgid are restored";
+const char *test_author	= "Andrey Vagin <avagin at openvz.org>";
+
+#define DETACH		1
+#define NEWSID		2
+#define CHANGESID	4
+#define DOUBLE_CHANGESID	8
+
+struct testcase {
+	int flags;
+	pid_t pid;
+	pid_t sid;
+};
+
+static struct testcase testcases[] = {
+			{DETACH, },
+			{NEWSID, },
+			{0, },
+			{DETACH|NEWSID, },
+			{CHANGESID, },
+			{DOUBLE_CHANGESID | CHANGESID, }
+		};
+/*
+    2     2 session00
+    4     4  \_ session00               # {NEWSID, },
+    2     5  \_ session00               # {0, },
+    8     8  \_ session00
+    2     9  |   \_ session00           # {CHANGESID, }
+   10    10  \_ session00
+   11    11      \_ session00
+    2    12          \_ session00       # {DOUBLE_CHANGESID | CHANGESID, }
+    2     3 session00                   # {DETACH, },
+    6     7 session00                   # {DETACH|NEWSID, },
+*/
+
+#define NUM_CASES (sizeof(testcases) / sizeof(struct testcase))
+
+static int fork_child(int i)
+{
+	int p[2];
+	int status, ret;
+	pid_t pid, sid;
+
+	ret = pipe(p);
+	if (ret) {
+		err("pipe() failed");
+		return 1;
+	}
+
+	pid = test_fork();
+	if (pid < 0) {
+		err("Can't fork");
+		return 1;
+	}
+
+	if (pid == 0) {
+		if (testcases[i].flags & NEWSID) {
+			sid = setsid();
+			if (sid == -1) {
+				err("setsid failed");
+				write(p[1], &sid, sizeof(sid));
+				exit(1);
+			}
+		}
+
+		if (testcases[i].flags & (DETACH | CHANGESID)) {
+			pid = test_fork();
+			if (pid < 0) {
+				write(p[1], &pid, sizeof(pid));
+				exit(1);
+			}
+		}
+
+		if (pid != 0) {
+			if (!(testcases[i].flags & CHANGESID))
+				exit(0);
+
+			sid = setsid();
+			if (sid == -1) {
+				err("setsid failed");
+				write(p[1], &sid, sizeof(sid));
+				exit(1);
+			}
+
+			wait(NULL);
+			if (getsid(getpid()) != sid) {
+				fail("The process %d (%x) has SID=%d (expected %d)",
+					pid, testcases[i].flags, sid, testcases[i].sid);
+				exit(1);
+			}
+			exit(0);
+		}
+
+		if (testcases[i].flags & DOUBLE_CHANGESID) {
+			pid = fork();
+			if (pid < 0) {
+				write(p[1], &pid, sizeof(pid));
+				exit(1);
+			}
+
+			if (pid == 0)
+				goto child;
+
+			sid = setsid();
+			if (sid == -1) {
+				err("setsid failed");
+				write(p[1], &sid, sizeof(sid));
+				exit(1);
+			}
+
+			wait(NULL);
+			if (getsid(getpid()) != sid) {
+				fail("The process %d (%x) has SID=%d (expected %d)",
+					pid, testcases[i].flags, sid, testcases[i].sid);
+				exit(1);
+			}
+			exit(0);
+		}
+
+child:
+		pid = getpid();
+		write(p[1], &pid, sizeof(pid));
+		close(p[1]);
+
+		test_waitsig();
+		pass();
+		exit(0);
+	}
+
+	close(p[1]);
+
+	if (testcases[i].flags & DETACH) {
+		pid_t ret;
+		ret = wait(&status);
+		if (ret != pid) {
+			err("wait return %d instead of %d", ret, pid);
+			kill(pid, SIGKILL);
+			return 1;
+		}
+	}
+
+	ret = read(p[0], &testcases[i].pid, sizeof(pid));
+	if (ret != sizeof(ret)) {
+		err("read failed");
+		return 1;
+	}
+
+	close(p[0]);
+
+	if (testcases[i].pid < 0) {
+		err("child failed");
+		return 1;
+	}
+
+	testcases[i].sid = getsid(testcases[i].pid);
+
+	return 0;
+}
+
+int main(int argc, char ** argv)
+{
+	int i, ret, err = 0, status;
+	pid_t pid;
+
+	test_init(argc, argv);
+
+	for (i = 0; i < NUM_CASES; i++)
+		if (fork_child(i))
+			break;
+
+	if (i != NUM_CASES) {
+		int j;
+		for (j = 0; j < i; j++)
+			kill(testcases[j].pid, SIGTERM);
+		return 1;
+	}
+
+	test_daemon();
+
+	test_waitsig();
+
+	for (i = 0; i < NUM_CASES; i++) {
+		pid_t pid = testcases[i].pid;
+		pid_t sid = getsid(pid);
+
+		if (sid != testcases[i].sid) {
+			fail("The process %d (%x) has SID=%d (expected %d)",
+				pid, testcases[i].flags, sid, testcases[i].sid);
+			err++;
+		}
+
+		ret = kill(pid, SIGKILL);
+		if (ret == -1) {
+			err("kill failed");
+			err++;
+		}
+		waitpid(pid, NULL, 0);
+
+		if (testcases[i].flags & CHANGESID) {
+			pid = wait(&status);
+			if (pid == -1) {
+				err("wait() failed");
+				err++;
+			}
+			if (!WIFEXITED(status) || WEXITSTATUS(status)) {
+				fail("The process with pid %d returns %d\n", pid, status);
+				err++;
+			}
+		}
+	}
+
+	pid = wait(&status);
+	if (pid != -1 || errno != ECHILD) {
+		err("%d isn't waited");
+		err++;
+	}
+
+	if (!err)
+		pass();
+
+	return err > 0;
+}
-- 
1.7.1



More information about the CRIU mailing list