Commit 814bd5d3 authored by Pavel Emelyanov's avatar Pavel Emelyanov

xids: Dump and restore tasks' pgid and sid

This is preriquisity for terminals handling and just a good
practice to save and restore everything we can :)

Not all combinations are supported. All the problems we still
have come from the inability to attach to group/session with
ID no tasks own as its PID.

This can be workarounded by fork()-ing this pid temporarily,
but we'd rather think in the direction of modifying the kernel
to give us direct syscall for this (oh my...)
Signed-off-by: 's avatarPavel Emelyanov <xemul@parallels.com>
parent 6f67bb8f
......@@ -1146,6 +1146,59 @@ static int collect_threads(struct pstree_item *item)
return ret;
}
/*
* Few words about sid and pgid handling.
*
* An axiom: session can only be changed on self, group -- on self or
* on one of self children.
*
* Conclusions:
* 1. both should better be saved in pstree.img so we can restore sid
* at the time we fork kids and pgid is just for harmony;
* 2. if we seized the parent these IDs* shouldn't change and it's safe
* to read and check them right at the seizing time.
*
* Easings:
* 1. with the existing setsid we can only reset sid to task's pid.
* Thus, if task escaped from its ancestors with sid we will not be
* able to easily restore this construction. Thus for now this is
* treated as "unsupported" (FIXME);
*
* 2. when task whose pid is equal to pgid/sid (i.e. leader) exits we
* lose the ability to restore the grp/session easily with the
* existing interfaces, thus we also treat this as temporarily
* unsupported (FIXME #2).
*/
static int check_xids(struct list_head *list)
{
struct pstree_item *p, *tmp;
list_for_each_entry(p, list, list) {
if (p->parent == NULL)
continue;
/* Easing #1 and #2 for sids */
if ((p->sid != p->pid) && (p->sid != p->parent->sid)) {
pr_err("SID mismatch on %d (%d/%d)\n",
p->pid, p->sid, p->parent->sid);
return -1;
}
/* Easing #2 for pgids */
list_for_each_entry(tmp, list, list)
if (tmp->pid == p->pgid)
break;
if (&tmp->list == list) {
pr_err("PGIG mismatch on %d (%d)\n",
p->pid, p->pgid);
return -1;
}
}
return 0;
}
static struct pstree_item *collect_task(pid_t pid, struct pstree_item *parent,
struct list_head *list)
{
......@@ -1299,6 +1352,9 @@ try_again:
}
}
if (!ret)
ret = check_xids(pstree_list);
if (ret)
return ret;
......
......@@ -732,6 +732,53 @@ static void sigchld_handler(int signal, siginfo_t *siginfo, void *data)
futex_abort_and_wake(&task_entries->nr_in_progress);
}
static void restore_sid(void)
{
pid_t sid;
/*
* SID can only be reset to pid or inherited from parent.
* Thus we restore it right here to let our kids inherit
* one in case they need it.
*
* PGIDs are restored late when all tasks are forked and
* we can call setpgid() on custom values.
*/
pr_info("Restoring %d to %d sid\n", me->pid, me->sid);
if (me->pid == me->sid) {
sid = setsid();
if (sid != me->sid) {
pr_perror("Can't restore sid (%d)", sid);
exit(1);
}
} else {
sid = getsid(getppid());
if (sid != me->sid) {
pr_err("Requested sid %d doesn't match inherited %d\n",
me->sid, sid);
exit(1);
}
}
}
static void restore_pgid(void)
{
pid_t pgid;
pr_info("Restoring %d to %d pgid\n", me->pid, me->pgid);
pgid = getpgrp();
if (me->pgid == pgid)
return;
pr_info("\twill call setpgid, mine pgid is %d\n", pgid);
if (setpgid(0, me->pgid) != 0) {
pr_perror("Can't restore pgid (%d/%d->%d)", me->pid, pgid, me->pgid);
exit(1);
}
}
static int restore_task_with_children(void *_arg)
{
struct cr_clone_arg *ca = _arg;
......@@ -762,6 +809,8 @@ static int restore_task_with_children(void *_arg)
exit(-1);
}
restore_sid();
/*
* The block mask will be restored in sigresturn.
*
......@@ -785,6 +834,8 @@ static int restore_task_with_children(void *_arg)
futex_dec_and_wake(&task_entries->nr_in_progress);
futex_wait_while(&task_entries->start, CR_STATE_FORKING);
restore_pgid();
return restore_one_task(me->pid);
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment