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

Submitted by Pavel Emelianov on April 27, 2016, 12:23 p.m.

Details

Message ID 5720AF32.4@virtuozzo.com
State Rejected
Headers show

Commit Message

Pavel Emelianov April 27, 2016, 12:23 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.

Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
---
 criu/cr-restore.c | 23 ++++++++++++++++++++++-
 1 file changed, 22 insertions(+), 1 deletion(-)

Patch hide | download patch | download mbox

diff --git a/criu/cr-restore.c b/criu/cr-restore.c
index 1b0354c..6e6179a 100644
--- a/criu/cr-restore.c
+++ b/criu/cr-restore.c
@@ -1985,6 +1985,21 @@  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.
+ *
+ * If we've ordered the sibling restore, then the
+ * fake root would be the task the parent will have
+ * to wait4() on, so except this case.
+ */
+static inline bool child_is_better(void)
+{
+	return (opts.unshare_flags & CLONE_NEWPID) && !opts.restore_sibling;
+}
+
 static int write_restored_pid(void)
 {
 	int pid;
@@ -1992,7 +2007,13 @@  static int write_restored_pid(void)
 	if (!opts.pidfile)
 		return 0;
 
-	pid = root_item->pid.real;
+	if (likely(!child_is_better()))
+		pid = root_item->pid.real;
+	else {
+		struct pstree_item *real_root;
+		real_root = list_first_entry(&root_item->children, struct pstree_item, sibling);
+		pid = real_root->pid.real;
+	}
 
 	if (write_pidfile(pid) < 0) {
 		pr_perror("Can't write pidfile");