|
@@ -819,9 +819,7 @@ static void forget_original_parent(struct task_struct *father)
|
|
*/
|
|
*/
|
|
static void exit_notify(struct task_struct *tsk, int group_dead)
|
|
static void exit_notify(struct task_struct *tsk, int group_dead)
|
|
{
|
|
{
|
|
- int signal;
|
|
|
|
bool autoreap;
|
|
bool autoreap;
|
|
- void *cookie;
|
|
|
|
|
|
|
|
/*
|
|
/*
|
|
* This does two things:
|
|
* This does two things:
|
|
@@ -852,16 +850,23 @@ static void exit_notify(struct task_struct *tsk, int group_dead)
|
|
* we have changed execution domain as these two values started
|
|
* we have changed execution domain as these two values started
|
|
* the same after a fork.
|
|
* the same after a fork.
|
|
*/
|
|
*/
|
|
- if (tsk->exit_signal != SIGCHLD && !task_detached(tsk) &&
|
|
|
|
|
|
+ if (thread_group_leader(tsk) && tsk->exit_signal != SIGCHLD &&
|
|
(tsk->parent_exec_id != tsk->real_parent->self_exec_id ||
|
|
(tsk->parent_exec_id != tsk->real_parent->self_exec_id ||
|
|
tsk->self_exec_id != tsk->parent_exec_id))
|
|
tsk->self_exec_id != tsk->parent_exec_id))
|
|
tsk->exit_signal = SIGCHLD;
|
|
tsk->exit_signal = SIGCHLD;
|
|
|
|
|
|
- signal = tracehook_notify_death(tsk, &cookie, group_dead);
|
|
|
|
- if (signal >= 0)
|
|
|
|
- autoreap = do_notify_parent(tsk, signal);
|
|
|
|
- else
|
|
|
|
- autoreap = (signal == DEATH_REAP);
|
|
|
|
|
|
+ if (unlikely(tsk->ptrace)) {
|
|
|
|
+ int sig = thread_group_leader(tsk) &&
|
|
|
|
+ thread_group_empty(tsk) &&
|
|
|
|
+ !ptrace_reparented(tsk) ?
|
|
|
|
+ tsk->exit_signal : SIGCHLD;
|
|
|
|
+ autoreap = do_notify_parent(tsk, sig);
|
|
|
|
+ } else if (thread_group_leader(tsk)) {
|
|
|
|
+ autoreap = thread_group_empty(tsk) &&
|
|
|
|
+ do_notify_parent(tsk, tsk->exit_signal);
|
|
|
|
+ } else {
|
|
|
|
+ autoreap = true;
|
|
|
|
+ }
|
|
|
|
|
|
tsk->exit_state = autoreap ? EXIT_DEAD : EXIT_ZOMBIE;
|
|
tsk->exit_state = autoreap ? EXIT_DEAD : EXIT_ZOMBIE;
|
|
|
|
|