summaryrefslogtreecommitdiff
path: root/kernel
diff options
context:
space:
mode:
authorDavid S. Miller <davem@kernel.bkbits.net>2004-07-01 07:12:53 -0700
committerDavid S. Miller <davem@kernel.bkbits.net>2004-07-01 07:12:53 -0700
commitbf5c4064091ffbdc2a958f7c3cbff0b400382e63 (patch)
treed68f8042e426154b21db76be09fa98938cf39149 /kernel
parent90d90ae3132f22bf526745d913c41448250165e3 (diff)
parentfbd7fa39d68c3828f324e556e3f61e462282021c (diff)
Merge davem@nuts.davemloft.net:/disk1/BK/net-2.6
into kernel.bkbits.net:/home/davem/net-2.6
Diffstat (limited to 'kernel')
-rw-r--r--kernel/exit.c34
-rw-r--r--kernel/futex.c2
-rw-r--r--kernel/power/pm.c2
3 files changed, 33 insertions, 5 deletions
diff --git a/kernel/exit.c b/kernel/exit.c
index 9cb99b471d2e..cf71b30d8bd5 100644
--- a/kernel/exit.c
+++ b/kernel/exit.c
@@ -594,7 +594,8 @@ static inline void reparent_thread(task_t *p, task_t *father, int traced)
* group, and if no such member exists, give it to
* the global child reaper process (ie "init")
*/
-static inline void forget_original_parent(struct task_struct * father)
+static inline void forget_original_parent(struct task_struct * father,
+ struct list_head *to_release)
{
struct task_struct *p, *reaper = father;
struct list_head *_p, *_n;
@@ -612,16 +613,34 @@ static inline void forget_original_parent(struct task_struct * father)
* Search them and reparent children.
*/
list_for_each_safe(_p, _n, &father->children) {
+ int ptrace;
p = list_entry(_p,struct task_struct,sibling);
+
+ ptrace = p->ptrace;
+
+ /* if father isn't the real parent, then ptrace must be enabled */
+ BUG_ON(father != p->real_parent && !ptrace);
+
if (father == p->real_parent) {
+ /* reparent with a reaper, real father it's us */
choose_new_parent(p, reaper, child_reaper);
reparent_thread(p, father, 0);
} else {
- ptrace_unlink (p);
+ /* reparent ptraced task to its real parent */
+ __ptrace_unlink (p);
if (p->state == TASK_ZOMBIE && p->exit_signal != -1 &&
thread_group_empty(p))
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 (unlikely(ptrace && p->state == TASK_ZOMBIE && p->exit_signal == -1))
+ list_add(&p->ptrace_list, to_release);
}
list_for_each_safe(_p, _n, &father->ptrace_children) {
p = list_entry(_p,struct task_struct,ptrace_list);
@@ -638,6 +657,7 @@ static void exit_notify(struct task_struct *tsk)
{
int state;
struct task_struct *t;
+ struct list_head ptrace_dead, *_p, *_n;
if (signal_pending(tsk) && !tsk->signal->group_exit
&& !thread_group_empty(tsk)) {
@@ -673,8 +693,10 @@ static void exit_notify(struct task_struct *tsk)
* jobs, send them a SIGHUP and then a SIGCONT. (POSIX 3.2.2.2)
*/
- forget_original_parent(tsk);
+ INIT_LIST_HEAD(&ptrace_dead);
+ forget_original_parent(tsk, &ptrace_dead);
BUG_ON(!list_empty(&tsk->children));
+ BUG_ON(!list_empty(&tsk->ptrace_children));
/*
* Check to see if any process groups have become orphaned
@@ -759,6 +781,12 @@ static void exit_notify(struct task_struct *tsk)
_raw_write_unlock(&tasklist_lock);
local_irq_enable();
+ list_for_each_safe(_p, _n, &ptrace_dead) {
+ list_del_init(_p);
+ t = list_entry(_p,struct task_struct,ptrace_list);
+ release_task(t);
+ }
+
/* If the process is dead, release it - nobody will wait for it */
if (state == TASK_DEAD)
release_task(tsk);
diff --git a/kernel/futex.c b/kernel/futex.c
index abae250cf73d..d9b9694fd2e8 100644
--- a/kernel/futex.c
+++ b/kernel/futex.c
@@ -276,7 +276,7 @@ static void wake_futex(struct futex_q *q)
* The waiting task can free the futex_q as soon as this is written,
* without taking any locks. This must come last.
*/
- q->lock_ptr = 0;
+ q->lock_ptr = NULL;
}
/*
diff --git a/kernel/power/pm.c b/kernel/power/pm.c
index 09d55363cefc..d1bc943072d4 100644
--- a/kernel/power/pm.c
+++ b/kernel/power/pm.c
@@ -282,7 +282,7 @@ struct pm_dev *pm_find(pm_dev_t type, struct pm_dev *from)
return dev;
entry = entry->next;
}
- return 0;
+ return NULL;
}
EXPORT_SYMBOL(pm_register);