[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