Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 295151
b: refs/heads/master
c: ebec18a
h: refs/heads/master
i:
  295149: eb9d4b8
  295147: ad96cf2
  295143: 10f8f60
  295135: bf09ff0
v: v3
  • Loading branch information
Lennart Poettering authored and Linus Torvalds committed Mar 23, 2012
1 parent 2529315 commit 6145372
Show file tree
Hide file tree
Showing 6 changed files with 55 additions and 6 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 953326cb60c1dff1bd3458d6468d16d75f2bcd61
refs/heads/master: ebec18a6d3aa1e7d84aab16225e87fd25170ec2b
3 changes: 3 additions & 0 deletions trunk/include/linux/prctl.h
Original file line number Diff line number Diff line change
Expand Up @@ -121,4 +121,7 @@
#define PR_SET_PTRACER 0x59616d61
# define PR_SET_PTRACER_ANY ((unsigned long)-1)

#define PR_SET_CHILD_SUBREAPER 36
#define PR_GET_CHILD_SUBREAPER 37

#endif /* _LINUX_PRCTL_H */
12 changes: 12 additions & 0 deletions trunk/include/linux/sched.h
Original file line number Diff line number Diff line change
Expand Up @@ -553,6 +553,18 @@ struct signal_struct {
int group_stop_count;
unsigned int flags; /* see SIGNAL_* flags below */

/*
* PR_SET_CHILD_SUBREAPER marks a process, like a service
* manager, to re-parent orphan (double-forking) child processes
* to this process instead of 'init'. The service manager is
* able to receive SIGCHLD signals and is able to investigate
* the process until it calls wait(). All children of this
* process will inherit a flag if they should look for a
* child_subreaper process at exit.
*/
unsigned int is_child_subreaper:1;
unsigned int has_child_subreaper:1;

/* POSIX.1b Interval Timers */
struct list_head posix_timers;

Expand Down
33 changes: 28 additions & 5 deletions trunk/kernel/exit.c
Original file line number Diff line number Diff line change
Expand Up @@ -687,11 +687,11 @@ static void exit_mm(struct task_struct * tsk)
}

/*
* When we die, we re-parent all our children.
* Try to give them to another thread in our thread
* group, and if no such member exists, give it to
* the child reaper process (ie "init") in our pid
* space.
* When we die, we re-parent all our children, and try to:
* 1. give them to another thread in our thread group, if such a member exists
* 2. give it to the first ancestor process which prctl'd itself as a
* child_subreaper for its children (like a service manager)
* 3. give it to the init process (PID 1) in our pid namespace
*/
static struct task_struct *find_new_reaper(struct task_struct *father)
__releases(&tasklist_lock)
Expand Down Expand Up @@ -722,6 +722,29 @@ static struct task_struct *find_new_reaper(struct task_struct *father)
* forget_original_parent() must move them somewhere.
*/
pid_ns->child_reaper = init_pid_ns.child_reaper;
} else if (father->signal->has_child_subreaper) {
struct task_struct *reaper;

/*
* Find the first ancestor marked as child_subreaper.
* Note that the code below checks same_thread_group(reaper,
* pid_ns->child_reaper). This is what we need to DTRT in a
* PID namespace. However we still need the check above, see
* http://marc.info/?l=linux-kernel&m=131385460420380
*/
for (reaper = father->real_parent;
reaper != &init_task;
reaper = reaper->real_parent) {
if (same_thread_group(reaper, pid_ns->child_reaper))
break;
if (!reaper->signal->is_child_subreaper)
continue;
thread = reaper;
do {
if (!(thread->flags & PF_EXITING))
return reaper;
} while_each_thread(reaper, thread);
}
}

return pid_ns->child_reaper;
Expand Down
3 changes: 3 additions & 0 deletions trunk/kernel/fork.c
Original file line number Diff line number Diff line change
Expand Up @@ -1051,6 +1051,9 @@ static int copy_signal(unsigned long clone_flags, struct task_struct *tsk)
sig->oom_score_adj = current->signal->oom_score_adj;
sig->oom_score_adj_min = current->signal->oom_score_adj_min;

sig->has_child_subreaper = current->signal->has_child_subreaper ||
current->signal->is_child_subreaper;

mutex_init(&sig->cred_guard_mutex);

return 0;
Expand Down
8 changes: 8 additions & 0 deletions trunk/kernel/sys.c
Original file line number Diff line number Diff line change
Expand Up @@ -1962,6 +1962,14 @@ SYSCALL_DEFINE5(prctl, int, option, unsigned long, arg2, unsigned long, arg3,
case PR_SET_MM:
error = prctl_set_mm(arg2, arg3, arg4, arg5);
break;
case PR_SET_CHILD_SUBREAPER:
me->signal->is_child_subreaper = !!arg2;
error = 0;
break;
case PR_GET_CHILD_SUBREAPER:
error = put_user(me->signal->is_child_subreaper,
(int __user *) arg2);
break;
default:
error = -EINVAL;
break;
Expand Down

0 comments on commit 6145372

Please sign in to comment.