mirror of
https://github.com/checkpoint-restore/criu.git
synced 2026-07-25 02:58:54 +00:00
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@openvz.org> Signed-off-by: Pavel Emelyanov <xemul@parallels.com>
This commit is contained in:
parent
84da534261
commit
f0606bc8d9
3 changed files with 74 additions and 33 deletions
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
103
tty.c
103
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,31 +926,11 @@ int collect_tty(void)
|
|||
return ret;
|
||||
}
|
||||
|
||||
static int dump_pty_info(int lfd, u32 id, const struct fd_parms *p, int major, int index)
|
||||
/* Make sure the ttys we're dumping do belong our process tree */
|
||||
int dump_verify_tty_sids(void)
|
||||
{
|
||||
TtyInfoEntry info = TTY_INFO_ENTRY__INIT;
|
||||
TermiosEntry termios = TERMIOS_ENTRY__INIT;
|
||||
TermiosEntry termios_locked = TERMIOS_ENTRY__INIT;
|
||||
WinsizeEntry winsize = WINSIZE_ENTRY__INIT;
|
||||
TtyPtyEntry pty = TTY_PTY_ENTRY__INIT;
|
||||
struct parasite_tty_args *pti;
|
||||
|
||||
struct termios t;
|
||||
struct winsize w;
|
||||
|
||||
int ret = -1;
|
||||
|
||||
/*
|
||||
* Make sure the structures the system provides us
|
||||
* correlates well with protobuf templates.
|
||||
*/
|
||||
BUILD_BUG_ON(ARRAY_SIZE(t.c_cc) < TERMIOS_NCC);
|
||||
BUILD_BUG_ON(sizeof(termios.c_cc) != sizeof(void *));
|
||||
BUILD_BUG_ON((sizeof(termios.c_cc) * TERMIOS_NCC) < sizeof(t.c_cc));
|
||||
|
||||
pti = parasite_dump_tty(p->ctl, p->fd);
|
||||
if (!pti)
|
||||
return -1;
|
||||
struct tty_dump_info *dinfo, *n;
|
||||
int ret = 0;
|
||||
|
||||
/*
|
||||
* There might be a cases where we get sid/pgid on
|
||||
|
|
@ -960,19 +950,66 @@ static int dump_pty_info(int lfd, u32 id, const struct fd_parms *p, int major, i
|
|||
* 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;
|
||||
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;
|
||||
TermiosEntry termios = TERMIOS_ENTRY__INIT;
|
||||
TermiosEntry termios_locked = TERMIOS_ENTRY__INIT;
|
||||
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;
|
||||
|
||||
int ret = -1;
|
||||
|
||||
/*
|
||||
* Make sure the structures the system provides us
|
||||
* correlates well with protobuf templates.
|
||||
*/
|
||||
BUILD_BUG_ON(ARRAY_SIZE(t.c_cc) < TERMIOS_NCC);
|
||||
BUILD_BUG_ON(sizeof(termios.c_cc) != sizeof(void *));
|
||||
BUILD_BUG_ON((sizeof(termios.c_cc) * TERMIOS_NCC) < sizeof(t.c_cc));
|
||||
|
||||
pti = parasite_dump_tty(p->ctl, p->fd);
|
||||
if (!pti)
|
||||
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;
|
||||
info.sid = pti->sid;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue