Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/checkpoint-restore/criu.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
authorMichał Cłapiński <mclapinski@google.com>2019-07-12 19:14:41 +0300
committerAndrei Vagin <avagin@gmail.com>2019-09-07 15:59:54 +0300
commit6606f246c21a8e1ff40b56087a360c1ff6fbe6bd (patch)
treed690775daaa6d3115e5aede5d4082842e89c567b /test
parentdb2777e73c3cf44ddb75aa4ab9f6e5bb88705571 (diff)
Add ZDTM tests for child subreaper property
1. Basic check if property is migrated 2. Check that property is restored for existing children 3. Check that child subreaper does not affect reparenting Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com> Signed-off-by: Michał Cłapiński <mclapinski@google.com> Reviewed-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
Diffstat (limited to 'test')
-rw-r--r--test/zdtm/static/Makefile3
-rw-r--r--test/zdtm/static/child_subreaper.c36
-rw-r--r--test/zdtm/static/child_subreaper_and_reparent.c142
-rw-r--r--test/zdtm/static/child_subreaper_and_reparent.desc1
-rw-r--r--test/zdtm/static/child_subreaper_existing_child.c138
5 files changed, 320 insertions, 0 deletions
diff --git a/test/zdtm/static/Makefile b/test/zdtm/static/Makefile
index 7799c0b0a..52bd00602 100644
--- a/test/zdtm/static/Makefile
+++ b/test/zdtm/static/Makefile
@@ -214,6 +214,9 @@ TST_NOFILE := \
selinux00 \
selinux01 \
selinux02 \
+ child_subreaper \
+ child_subreaper_existing_child \
+ child_subreaper_and_reparent \
# jobctl00 \
ifneq ($(SRCARCH),arm)
diff --git a/test/zdtm/static/child_subreaper.c b/test/zdtm/static/child_subreaper.c
new file mode 100644
index 000000000..267795249
--- /dev/null
+++ b/test/zdtm/static/child_subreaper.c
@@ -0,0 +1,36 @@
+#include <stdlib.h>
+#include <sys/prctl.h>
+
+#include "zdtmtst.h"
+
+const char *test_doc = "Check that child subreaper attribute is restored";
+const char *test_author = "Michał Cłapiński <mclapinski@google.com>";
+
+int main(int argc, char **argv)
+{
+ test_init(argc, argv);
+
+ int cs_before = 1;
+ int ret = prctl(PR_SET_CHILD_SUBREAPER, cs_before, 0, 0, 0);
+ if (ret) {
+ pr_perror("Can't set child subreaper attribute, err = %d", ret);
+ exit(1);
+ }
+
+ test_daemon();
+ test_waitsig();
+
+ int cs_after;
+ ret = prctl(PR_GET_CHILD_SUBREAPER, (unsigned long)&cs_after, 0, 0, 0);
+ if (ret) {
+ pr_perror("Can't get child subreaper attribute, err = %d", ret);
+ exit(1);
+ }
+
+ if (cs_before != cs_after)
+ fail("%d != %d\n", cs_before, cs_after);
+ else
+ pass();
+
+ return 0;
+}
diff --git a/test/zdtm/static/child_subreaper_and_reparent.c b/test/zdtm/static/child_subreaper_and_reparent.c
new file mode 100644
index 000000000..57943a67b
--- /dev/null
+++ b/test/zdtm/static/child_subreaper_and_reparent.c
@@ -0,0 +1,142 @@
+#include <unistd.h>
+#include <stdlib.h>
+#include <signal.h>
+#include <sys/mman.h>
+#include <sys/wait.h>
+#include <sys/prctl.h>
+
+#include "zdtmtst.h"
+#include "lock.h"
+
+const char *test_doc = "Check that child subreaper does not affect reparenting";
+const char *test_author = "Pavel Tikhomirov <ptikhomirov@virtuozzo.com>";
+
+enum {
+ TEST_FORK,
+ TEST_SAVE,
+ TEST_CRIU,
+ TEST_CHECK,
+ TEST_EXIT,
+};
+
+struct shared {
+ futex_t fstate;
+ int parent_before_cr;
+ int parent_after_cr;
+} *sh;
+
+int orphan()
+{
+ /*
+ * Wait until reparented to the pidns init. (By waiting
+ * for the SUBREAPER to reap our parent.)
+ */
+ futex_wait_until(&sh->fstate, TEST_SAVE);
+
+ sh->parent_before_cr = getppid();
+
+ /* Return the control back to MAIN worker to do C/R */
+ futex_set_and_wake(&sh->fstate, TEST_CRIU);
+ futex_wait_until(&sh->fstate, TEST_CHECK);
+
+ sh->parent_after_cr = getppid();
+
+ futex_set_and_wake(&sh->fstate, TEST_EXIT);
+ return 0;
+}
+
+int helper()
+{
+ int pid;
+
+ pid = fork();
+ if (pid < 0) {
+ pr_perror("Failed to fork");
+ return 1;
+ } else if (pid == 0) {
+ exit(orphan());
+ }
+ return 0;
+}
+
+int subreaper()
+{
+ int pid, ret, status;
+
+ setsid();
+
+ pid = fork();
+ if (pid < 0) {
+ pr_perror("Failed to fork");
+ return 1;
+ } else if (pid == 0) {
+ exit(helper());
+ }
+
+ /* Reap the HELPER */
+ waitpid(pid, &status, 0);
+ if (!WIFEXITED(status) || WEXITSTATUS(status)) {
+ pr_perror("Wrong exit status for helper: %d", status);
+ return 1;
+ }
+
+ ret = prctl(PR_SET_CHILD_SUBREAPER, 1, 0, 0, 0);
+ if (ret) {
+ pr_perror("Can't set child subreaper attribute, err = %d", ret);
+ return 1;
+ }
+
+ /* Give control to ORPHAN to save it's parent */
+ futex_set_and_wake(&sh->fstate, TEST_SAVE);
+ futex_wait_until(&sh->fstate, TEST_EXIT);
+ return 0;
+}
+
+int main(int argc, char **argv)
+{
+ int pid, status;
+
+ sh = mmap(NULL, sizeof(struct shared), PROT_WRITE | PROT_READ, MAP_SHARED | MAP_ANONYMOUS, -1, 0);
+ if (sh == MAP_FAILED) {
+ pr_perror("Failed to alloc shared region");
+ exit(1);
+ }
+
+ futex_set(&sh->fstate, TEST_FORK);
+
+ test_init(argc, argv);
+
+ setsid();
+
+ pid = fork();
+ if (pid < 0) {
+ pr_perror("Failed to fork");
+ exit(1);
+ } else if (pid == 0) {
+ exit(subreaper());
+ }
+
+ /* Wait until ORPHAN is ready to C/R */
+ futex_wait_until(&sh->fstate, TEST_CRIU);
+
+ test_daemon();
+ test_waitsig();
+
+ /* Give control to ORPHAN to check it's parent */
+ futex_set_and_wake(&sh->fstate, TEST_CHECK);
+ futex_wait_until(&sh->fstate, TEST_EXIT);
+
+ /* Cleanup */
+ while (wait(&status) > 0) {
+ if (!WIFEXITED(status) || WEXITSTATUS(status)) {
+ fail("Wrong exit status: %d", status);
+ return 1;
+ }
+ }
+
+ if (sh->parent_before_cr != sh->parent_after_cr)
+ fail("Parent mismatch before %d after %d", sh->parent_before_cr, sh->parent_after_cr);
+ else
+ pass();
+ return 0;
+}
diff --git a/test/zdtm/static/child_subreaper_and_reparent.desc b/test/zdtm/static/child_subreaper_and_reparent.desc
new file mode 100644
index 000000000..6c4afe5f0
--- /dev/null
+++ b/test/zdtm/static/child_subreaper_and_reparent.desc
@@ -0,0 +1 @@
+{'flavor': 'ns uns'}
diff --git a/test/zdtm/static/child_subreaper_existing_child.c b/test/zdtm/static/child_subreaper_existing_child.c
new file mode 100644
index 000000000..28e9dbb8a
--- /dev/null
+++ b/test/zdtm/static/child_subreaper_existing_child.c
@@ -0,0 +1,138 @@
+#include <unistd.h>
+#include <stdlib.h>
+#include <sys/mman.h>
+#include <sys/wait.h>
+#include <sys/prctl.h>
+
+#include "zdtmtst.h"
+#include "lock.h"
+
+const char *test_doc = "Check that property is restored for existing children";
+const char *test_author = "Michał Cłapiński <mclapinski@google.com>";
+
+enum {
+ TEST_FORK,
+ TEST_CRIU,
+ TEST_DIE,
+ TEST_CHECK,
+ TEST_EXIT,
+};
+
+struct shared {
+ futex_t fstate;
+ int ppid_after_reparent;
+} *sh;
+
+
+int orphan()
+{
+ /* Return the control back to MAIN worker to do C/R */
+ futex_set_and_wake(&sh->fstate, TEST_CRIU);
+ futex_wait_until(&sh->fstate, TEST_CHECK);
+
+ sh->ppid_after_reparent = getppid();
+
+ futex_set_and_wake(&sh->fstate, TEST_EXIT);
+ return 0;
+}
+
+int helper()
+{
+ int pid;
+
+ pid = fork();
+ if (pid < 0) {
+ pr_perror("Failed to fork");
+ return 1;
+ } else if (pid == 0) {
+ exit(orphan());
+ }
+
+ futex_wait_until(&sh->fstate, TEST_DIE);
+ return 0;
+}
+
+int subreaper()
+{
+ int pid, ret, status;
+
+ pid = fork();
+ if (pid < 0) {
+ pr_perror("Failed to fork");
+ return 1;
+ } else if (pid == 0) {
+ exit(helper());
+ }
+
+ ret = prctl(PR_SET_CHILD_SUBREAPER, 1, 0, 0, 0);
+ if (ret) {
+ pr_perror("Can't set child subreaper attribute, err = %d", ret);
+ return 1;
+ }
+
+ /* Reap the HELPER */
+ waitpid(pid, &status, 0);
+ if (!WIFEXITED(status) || WEXITSTATUS(status)) {
+ pr_perror("Wrong exit status for HELPER: %d", status);
+ return 1;
+ }
+
+ /* Give control to ORPHAN so it can check its parent */
+ futex_set_and_wake(&sh->fstate, TEST_CHECK);
+ futex_wait_until(&sh->fstate, TEST_EXIT);
+
+ /* Cleanup: reap the ORPHAN */
+ wait(&status);
+ if (!WIFEXITED(status) || WEXITSTATUS(status)) {
+ pr_perror("Wrong exit status for ORPHAN: %d", status);
+ return 1;
+ }
+
+ return 0;
+}
+
+int main(int argc, char **argv)
+{
+ int pid, status;
+
+ sh = mmap(NULL, sizeof(struct shared), PROT_WRITE | PROT_READ, MAP_SHARED | MAP_ANONYMOUS, -1, 0);
+ if (sh == MAP_FAILED) {
+ pr_perror("Failed to alloc shared region");
+ exit(1);
+ }
+
+ futex_set(&sh->fstate, TEST_FORK);
+
+ test_init(argc, argv);
+
+ pid = fork();
+ if (pid < 0) {
+ pr_perror("Failed to fork");
+ exit(1);
+ } else if (pid == 0) {
+ exit(subreaper());
+ }
+
+ /* Wait until ORPHAN is ready to C/R */
+ futex_wait_until(&sh->fstate, TEST_CRIU);
+
+ test_daemon();
+ test_waitsig();
+
+ /* Give control to HELPER so it can die */
+ futex_set_and_wake(&sh->fstate, TEST_DIE);
+ futex_wait_until(&sh->fstate, TEST_EXIT);
+
+ /* Cleanup: reap the SUBREAPER */
+ waitpid(pid, &status, 0);
+ if (!WIFEXITED(status) || WEXITSTATUS(status)) {
+ fail("Wrong exit status: %d", status);
+ return 1;
+ }
+
+ if (sh->ppid_after_reparent != pid)
+ fail("Orphan was reparented to %d instead of %d", sh->ppid_after_reparent, pid);
+ else
+ pass();
+ return 0;
+}