|
@@ -52,6 +52,11 @@
|
|
|
|
|
|
static void exit_mm(struct task_struct * tsk);
|
|
static void exit_mm(struct task_struct * tsk);
|
|
|
|
|
|
|
|
+static inline int task_detached(struct task_struct *p)
|
|
|
|
+{
|
|
|
|
+ return p->exit_signal == -1;
|
|
|
|
+}
|
|
|
|
+
|
|
static void __unhash_process(struct task_struct *p)
|
|
static void __unhash_process(struct task_struct *p)
|
|
{
|
|
{
|
|
nr_threads--;
|
|
nr_threads--;
|
|
@@ -160,7 +165,7 @@ repeat:
|
|
zap_leader = 0;
|
|
zap_leader = 0;
|
|
leader = p->group_leader;
|
|
leader = p->group_leader;
|
|
if (leader != p && thread_group_empty(leader) && leader->exit_state == EXIT_ZOMBIE) {
|
|
if (leader != p && thread_group_empty(leader) && leader->exit_state == EXIT_ZOMBIE) {
|
|
- BUG_ON(leader->exit_signal == -1);
|
|
|
|
|
|
+ BUG_ON(task_detached(leader));
|
|
do_notify_parent(leader, leader->exit_signal);
|
|
do_notify_parent(leader, leader->exit_signal);
|
|
/*
|
|
/*
|
|
* If we were the last child thread and the leader has
|
|
* If we were the last child thread and the leader has
|
|
@@ -170,7 +175,7 @@ repeat:
|
|
* do_notify_parent() will have marked it self-reaping in
|
|
* do_notify_parent() will have marked it self-reaping in
|
|
* that case.
|
|
* that case.
|
|
*/
|
|
*/
|
|
- zap_leader = (leader->exit_signal == -1);
|
|
|
|
|
|
+ zap_leader = task_detached(leader);
|
|
}
|
|
}
|
|
|
|
|
|
write_unlock_irq(&tasklist_lock);
|
|
write_unlock_irq(&tasklist_lock);
|
|
@@ -721,14 +726,14 @@ reparent_thread(struct task_struct *p, struct task_struct *father, int traced)
|
|
return;
|
|
return;
|
|
|
|
|
|
/* We don't want people slaying init. */
|
|
/* We don't want people slaying init. */
|
|
- if (p->exit_signal != -1)
|
|
|
|
|
|
+ if (!task_detached(p))
|
|
p->exit_signal = SIGCHLD;
|
|
p->exit_signal = SIGCHLD;
|
|
|
|
|
|
/* If we'd notified the old parent about this child's death,
|
|
/* If we'd notified the old parent about this child's death,
|
|
* also notify the new parent.
|
|
* also notify the new parent.
|
|
*/
|
|
*/
|
|
if (!traced && p->exit_state == EXIT_ZOMBIE &&
|
|
if (!traced && p->exit_state == EXIT_ZOMBIE &&
|
|
- p->exit_signal != -1 && thread_group_empty(p))
|
|
|
|
|
|
+ !task_detached(p) && thread_group_empty(p))
|
|
do_notify_parent(p, p->exit_signal);
|
|
do_notify_parent(p, p->exit_signal);
|
|
|
|
|
|
kill_orphaned_pgrp(p, father);
|
|
kill_orphaned_pgrp(p, father);
|
|
@@ -781,18 +786,18 @@ static void forget_original_parent(struct task_struct *father)
|
|
} else {
|
|
} else {
|
|
/* reparent ptraced task to its real parent */
|
|
/* reparent ptraced task to its real parent */
|
|
__ptrace_unlink (p);
|
|
__ptrace_unlink (p);
|
|
- if (p->exit_state == EXIT_ZOMBIE && p->exit_signal != -1 &&
|
|
|
|
|
|
+ if (p->exit_state == EXIT_ZOMBIE && !task_detached(p) &&
|
|
thread_group_empty(p))
|
|
thread_group_empty(p))
|
|
do_notify_parent(p, p->exit_signal);
|
|
do_notify_parent(p, p->exit_signal);
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
/*
|
|
- * if the ptraced child is a zombie with exit_signal == -1
|
|
|
|
- * we must collect it before we exit, or it will remain
|
|
|
|
- * zombie forever since we prevented it from self-reap itself
|
|
|
|
- * while it was being traced by us, to be able to see it in wait4.
|
|
|
|
|
|
+ * if the ptraced child is a detached zombie we must collect
|
|
|
|
+ * it before we exit, or it will remain zombie forever since
|
|
|
|
+ * we prevented it from self-reap itself while it was being
|
|
|
|
+ * traced by us, to be able to see it in wait4.
|
|
*/
|
|
*/
|
|
- if (unlikely(ptrace && p->exit_state == EXIT_ZOMBIE && p->exit_signal == -1))
|
|
|
|
|
|
+ if (unlikely(ptrace && p->exit_state == EXIT_ZOMBIE && task_detached(p)))
|
|
list_add(&p->ptrace_list, &ptrace_dead);
|
|
list_add(&p->ptrace_list, &ptrace_dead);
|
|
}
|
|
}
|
|
|
|
|
|
@@ -849,26 +854,26 @@ 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 && tsk->exit_signal != -1 &&
|
|
|
|
|
|
+ if (tsk->exit_signal != SIGCHLD && !task_detached(tsk) &&
|
|
(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)
|
|
|
|
- && !capable(CAP_KILL))
|
|
|
|
|
|
+ tsk->self_exec_id != tsk->parent_exec_id) &&
|
|
|
|
+ !capable(CAP_KILL))
|
|
tsk->exit_signal = SIGCHLD;
|
|
tsk->exit_signal = SIGCHLD;
|
|
|
|
|
|
-
|
|
|
|
/* If something other than our normal parent is ptracing us, then
|
|
/* If something other than our normal parent is ptracing us, then
|
|
* send it a SIGCHLD instead of honoring exit_signal. exit_signal
|
|
* send it a SIGCHLD instead of honoring exit_signal. exit_signal
|
|
* only has special meaning to our real parent.
|
|
* only has special meaning to our real parent.
|
|
*/
|
|
*/
|
|
- if (tsk->exit_signal != -1 && thread_group_empty(tsk)) {
|
|
|
|
- int signal = tsk->parent == tsk->real_parent ? tsk->exit_signal : SIGCHLD;
|
|
|
|
|
|
+ if (!task_detached(tsk) && thread_group_empty(tsk)) {
|
|
|
|
+ int signal = (tsk->parent == tsk->real_parent)
|
|
|
|
+ ? tsk->exit_signal : SIGCHLD;
|
|
do_notify_parent(tsk, signal);
|
|
do_notify_parent(tsk, signal);
|
|
} else if (tsk->ptrace) {
|
|
} else if (tsk->ptrace) {
|
|
do_notify_parent(tsk, SIGCHLD);
|
|
do_notify_parent(tsk, SIGCHLD);
|
|
}
|
|
}
|
|
|
|
|
|
state = EXIT_ZOMBIE;
|
|
state = EXIT_ZOMBIE;
|
|
- if (tsk->exit_signal == -1 && likely(!tsk->ptrace))
|
|
|
|
|
|
+ if (task_detached(tsk) && likely(!tsk->ptrace))
|
|
state = EXIT_DEAD;
|
|
state = EXIT_DEAD;
|
|
tsk->exit_state = state;
|
|
tsk->exit_state = state;
|
|
|
|
|
|
@@ -1173,7 +1178,7 @@ static int eligible_child(enum pid_type type, struct pid *pid, int options,
|
|
* Do not consider detached threads that are
|
|
* Do not consider detached threads that are
|
|
* not ptraced:
|
|
* not ptraced:
|
|
*/
|
|
*/
|
|
- if (p->exit_signal == -1 && !p->ptrace)
|
|
|
|
|
|
+ if (task_detached(p) && !p->ptrace)
|
|
return 0;
|
|
return 0;
|
|
|
|
|
|
/* Wait for all children (clone and not) if __WALL is set;
|
|
/* Wait for all children (clone and not) if __WALL is set;
|
|
@@ -1365,9 +1370,9 @@ static int wait_task_zombie(struct task_struct *p, int noreap,
|
|
* If it's still not detached after that, don't release
|
|
* If it's still not detached after that, don't release
|
|
* it now.
|
|
* it now.
|
|
*/
|
|
*/
|
|
- if (p->exit_signal != -1) {
|
|
|
|
|
|
+ if (!task_detached(p)) {
|
|
do_notify_parent(p, p->exit_signal);
|
|
do_notify_parent(p, p->exit_signal);
|
|
- if (p->exit_signal != -1) {
|
|
|
|
|
|
+ if (!task_detached(p)) {
|
|
p->exit_state = EXIT_ZOMBIE;
|
|
p->exit_state = EXIT_ZOMBIE;
|
|
p = NULL;
|
|
p = NULL;
|
|
}
|
|
}
|