[v2,2/4] criu: Write child pid into pidfile

Submitted by Pavel Emelianov on May 4, 2016, 4:02 p.m.

Details

Message ID 572A1D29.7060808@virtuozzo.com
State Superseded
Commit 9d51afaecc502755180d369c5599b4ed894382cd
Headers show

Commit Message

Pavel Emelianov May 4, 2016, 4:02 p.m.
When restoring tasks into --unshare pid context the
root_item actually represents fake init task. For the
external observer this root's (the only) child is
the task that got effectively restored, to put the
latter's pid into pidfile.

v2: Add helper for getting the pid
    Ban --restore-sibling --unshare pid combination

Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
---
 criu/cr-restore.c     | 20 ++++++++++++++++++--
 criu/include/pstree.h |  2 +-
 criu/pstree.c         | 10 ++++++++++
 3 files changed, 29 insertions(+), 3 deletions(-)

Patch hide | download patch | download mbox

diff --git a/criu/cr-restore.c b/criu/cr-restore.c
index 4e45a97..ef77abe 100644
--- a/criu/cr-restore.c
+++ b/criu/cr-restore.c
@@ -1988,6 +1988,23 @@  static void restore_origin_ns_hook(void)
 		pr_err("Restore original /proc/self/loginuid failed");
 }
 
+/*
+ * In this case the task that we have just restored
+ * is really the root_item's only child. So write
+ * its pid into pidfile to make everybody else see
+ * the correct task.
+ */
+pid_t restored_root_pid(void)
+{
+	struct pstree_item *r;
+
+	r = root_item;
+	if (opts.unshare_flags & CLONE_NEWPID)
+		r = list_first_entry(&r->children, struct pstree_item, sibling);
+
+	return r->pid.real;
+}
+
 static int write_restored_pid(void)
 {
 	int pid;
@@ -1995,8 +2012,7 @@  static int write_restored_pid(void)
 	if (!opts.pidfile)
 		return 0;
 
-	pid = root_item->pid.real;
-
+	pid = restored_root_pid();
 	if (write_pidfile(pid) < 0) {
 		pr_perror("Can't write pidfile");
 		return -1;
diff --git a/criu/include/pstree.h b/criu/include/pstree.h
index 6ff8781..970534a 100644
--- a/criu/include/pstree.h
+++ b/criu/include/pstree.h
@@ -96,6 +96,6 @@  extern int pstree_alloc_cores(struct pstree_item *item);
 extern void pstree_free_cores(struct pstree_item *item);
 
 extern int collect_pstree_ids(void);
-
 extern int preorder_pstree_traversal(struct pstree_item *item, int (*f)(struct pstree_item *));
+extern pid_t restored_root_pid(void);
 #endif /* __CR_PSTREE_H__ */
diff --git a/criu/pstree.c b/criu/pstree.c
index 408ce2b..a7d2790 100644
--- a/criu/pstree.c
+++ b/criu/pstree.c
@@ -909,6 +909,16 @@  static int prepare_pstree_for_unshare(void)
 			!(rsti(root_item)->clone_flags & CLONE_NEWPID)) {
 		struct pstree_item *fake_root;
 
+		if (opts.restore_sibling) {
+			/*
+			 * In this case the restored root task will be
+			 * the fake init one, not the original init, so
+			 * don't allow this (for now).
+			 */
+			pr_err("Unshare pidns for sibling is not supported\n");
+			return -1;
+		}
+
 		fake_root = lookup_create_item(INIT_PID);
 		if (fake_root == NULL)
 			return -1;