[CRIU] Re: [PATCH 09/10] tty: Introduce deferred dumping of tty peers

Cyrill Gorcunov gorcunov at openvz.org
Fri Oct 26 17:25:33 EDT 2012


On Sat, Oct 27, 2012 at 12:32:00AM +0400, Pavel Emelyanov wrote:
> On 10/27/2012 12:28 AM, Cyrill Gorcunov wrote:
> > On Sat, Oct 27, 2012 at 12:23:08AM +0400, Pavel Emelyanov wrote:
> >>>>
> >>>> OK. Let's move forward. This find_first_sid() is required to make sure
> >>>> that the session leader of tty's session is with us, correct?
> >>>
> >>> Yes, exactly. We need to figure out if we manage to restore this peer.
> >>
> >> Then I propose to dump ttys in the old place and just make this check deferred.
> > 
> > It doesn't change much -- I still need to carry parameters associated with ttys
> > so I think deferred dumping is simplier.
> 
> Not all parameters, but sid only.
> 
> > But'll take a look. On the other hands, may we do that on top? At least the
> > patches brings current c/r process back to life over all apps I've been
> > testing and they do no change any external interface or format.
> 
> Just resend patch #9

Here we go
-------------- next part --------------
>From 2558e1f3dea3d6f556d8dece46a7350206777f55 Mon Sep 17 00:00:00 2001
From: Cyrill Gorcunov <gorcunov at openvz.org>
Date: Sat, 27 Oct 2012 01:15:48 +0400
Subject: [PATCH] tty: Introduce deferred checking of tty sids

The dumping of tty peers is somewhat tricky. And it became more
complex once we allowed to migrate/inherit sessions.

It's being found (in screen c/r) that we've a problem in looking
up of session leaders while dumping tty.

Let me explain with more details. Here is an example of screen
session

  PID   GID   SID
20567 20567 20567           SCREEN
20568 20568 20568  pts/3     \_ /bin/bash

The screen opens master peer (ptmx) and then provides
bash the slave peer (pts/3) where bash sets up a session
leader on it.

Thus we get interesting scenario -- our pstree construction
is done in lazy fashion, we run parasite code to fetch sid/pgid
of a process tree item only when we're really dumping the task.

Thus when we start dumping ptmx peer (which belongs to SCREEN)
we've not yet constructed the process tree item for children
(ie /bin/bash) and the lookup function in tty code (which walks
over all process items in a tree) simply fails to find sid of
child, because we've not yet dumped it.

Thus, to resolve such situation we verify tty sids at late stage
of dumping.

Signed-off-by: Cyrill Gorcunov <gorcunov at openvz.org>
---
 cr-dump.c     |    3 ++
 include/tty.h |    1 +
 tty.c         |   97 +++++++++++++++++++++++++++++++++++++++-----------------
 3 files changed, 71 insertions(+), 30 deletions(-)

diff --git a/cr-dump.c b/cr-dump.c
index 76cd762..d9b8e1c 100644
--- a/cr-dump.c
+++ b/cr-dump.c
@@ -1671,6 +1671,9 @@ int cr_dump_tasks(pid_t pid, const struct cr_options *opts)
 			goto err;
 	}
 
+	if (dump_verify_tty_sids())
+		goto err;
+
 	if (dump_zombies())
 		goto err;
 
diff --git a/include/tty.h b/include/tty.h
index a0f9408..c6170ec 100644
--- a/include/tty.h
+++ b/include/tty.h
@@ -14,6 +14,7 @@
 #define PTS_FMT		"/dev/pts/%d"
 
 extern int dump_tty(struct fd_parms *p, int lfd, const struct cr_fdset *set);
+extern int dump_verify_tty_sids(void);
 extern int collect_tty(void);
 extern int prepare_shared_tty(void);
 extern int tty_setup_slavery(void);
diff --git a/tty.c b/tty.c
index 3e4f2ec..27d79a0 100644
--- a/tty.c
+++ b/tty.c
@@ -82,6 +82,16 @@ struct tty_info {
 	bool				create;
 };
 
+struct tty_dump_info {
+	struct list_head		list;
+
+	u32				id;
+	pid_t				sid;
+	pid_t				pgrp;
+	int				fd;
+	int				major;
+};
+
 static LIST_HEAD(all_tty_info_entries);
 static LIST_HEAD(all_ttys);
 static int self_stdin = -1;
@@ -916,6 +926,51 @@ int collect_tty(void)
 	return ret;
 }
 
+/* Make sure the ttys we're dumping do belong our process tree */
+int dump_verify_tty_sids(void)
+{
+	struct tty_dump_info *dinfo, *n;
+	int ret = 0;
+
+	/*
+	 * There might be a cases where we get sid/pgid on
+	 * slave peer. For example the application is running
+	 * with redirection and we're migrating shell job.
+	 *
+	 * # ./app < /dev/zero > /dev/zero &2>1
+	 *
+	 * Which produce a tree like
+	 *          PID   PPID  PGID  SID
+	 * root     23786 23784 23786 23786 pts/0 \_ -bash
+	 * root     24246 23786 24246 23786 pts/0   \_ ./app
+	 *
+	 * And the application goes background, then we dump
+	 * it from the same shell.
+	 *
+	 * In this case we simply zap sid/pgid and inherit
+	 * the peer from the current terminal on restore.
+	 */
+	list_for_each_entry_safe(dinfo, n, &all_ttys, list) {
+		if (!ret && dinfo->sid) {
+			struct pstree_item *item = find_first_sid(dinfo->sid);
+
+			if (!item || item->pid.virt != dinfo->sid) {
+				if (!opts.shell_job) {
+					pr_err("Found sid %d pgid %d (%s) on peer fd %d. "
+					       "Missing option?\n",
+					       dinfo->sid, dinfo->pgrp,
+					       tty_type(dinfo->major),
+					       dinfo->fd);
+					ret = -1;
+				}
+			}
+		}
+		xfree(dinfo);
+	}
+
+	return ret;
+}
+
 static int dump_pty_info(int lfd, u32 id, const struct fd_parms *p, int major, int index)
 {
 	TtyInfoEntry info		= TTY_INFO_ENTRY__INIT;
@@ -924,6 +979,7 @@ static int dump_pty_info(int lfd, u32 id, const struct fd_parms *p, int major, i
 	WinsizeEntry winsize		= WINSIZE_ENTRY__INIT;
 	TtyPtyEntry pty			= TTY_PTY_ENTRY__INIT;
 	struct parasite_tty_args *pti;
+	struct tty_dump_info *dinfo;
 
 	struct termios t;
 	struct winsize w;
@@ -942,36 +998,17 @@ static int dump_pty_info(int lfd, u32 id, const struct fd_parms *p, int major, i
 	if (!pti)
 		return -1;
 
-	/*
-	 * There might be a cases where we get sid/pgid on
-	 * slave peer. For example the application is running
-	 * with redirection and we're migrating shell job.
-	 *
-	 * # ./app < /dev/zero > /dev/zero &2>1
-	 *
-	 * Which produce a tree like
-	 *          PID   PPID  PGID  SID
-	 * root     23786 23784 23786 23786 pts/0 \_ -bash
-	 * root     24246 23786 24246 23786 pts/0   \_ ./app
-	 *
-	 * And the application goes background, then we dump
-	 * it from the same shell.
-	 *
-	 * In this case we simply zap sid/pgid and inherit
-	 * the peer from the current terminal on restore.
-	 */
-	if (pti->sid) {
-		struct pstree_item *item = find_first_sid(pti->sid);
-		if (!item || item->pid.virt != pti->sid) {
-			if (!opts.shell_job) {
-				pr_err("Found sid %d pgid %d (%s) on peer fd %d. "
-				       "Missing option?\n",
-				       pti->sid, pti->pgrp,
-				       tty_type(major), p->fd);
-				return -1;
-			}
-		}
-	}
+	dinfo = xmalloc(sizeof(*dinfo));
+	if (!dinfo)
+		return -1;
+
+	dinfo->id		= id;
+	dinfo->sid		= pti->sid;
+	dinfo->pgrp		= pti->pgrp;
+	dinfo->fd		= p->fd;
+	dinfo->major		= major;
+
+	list_add_tail(&dinfo->list, &all_ttys);
 
 	info.id			= id;
 	info.type		= TTY_TYPE__PTY;
-- 
1.7.7.6



More information about the CRIU mailing list