patch-2.4.0-test8 linux/kernel/exit.c
Next file: linux/kernel/fork.c
Previous file: linux/ipc/shm.c
Back to the patch index
Back to the overall index
- Lines: 178
- Date:
Fri Sep 1 18:08:46 2000
- Orig file:
v2.4.0-test7/linux/kernel/exit.c
- Orig date:
Wed Aug 23 18:36:39 2000
diff -u --recursive --new-file v2.4.0-test7/linux/kernel/exit.c linux/kernel/exit.c
@@ -144,17 +144,29 @@
return retval;
}
+/*
+ * When we die, we re-parent all our children.
+ * Try to give them to another thread in our process
+ * 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)
{
- struct task_struct * p;
+ struct task_struct * p, *reaper;
read_lock(&tasklist_lock);
+
+ /* Next in our thread group */
+ reaper = next_thread(father);
+ if (reaper == father)
+ reaper = child_reaper;
+
for_each_task(p) {
if (p->p_opptr == father) {
/* We dont want people slaying init */
p->exit_signal = SIGCHLD;
p->self_exec_id++;
- p->p_opptr = child_reaper; /* init */
+ p->p_opptr = reaper;
if (p->pdeath_signal) send_sig(p->pdeath_signal, p, 0);
}
}
@@ -255,26 +267,6 @@
__exit_fs(tsk);
}
-static inline void __exit_sighand(struct task_struct *tsk)
-{
- struct signal_struct * sig = tsk->sig;
-
- if (sig) {
- spin_lock_irq(&tsk->sigmask_lock);
- tsk->sig = NULL;
- spin_unlock_irq(&tsk->sigmask_lock);
- if (atomic_dec_and_test(&sig->count))
- kmem_cache_free(sigact_cachep, sig);
- }
-
- flush_signals(tsk);
-}
-
-void exit_sighand(struct task_struct *tsk)
-{
- __exit_sighand(tsk);
-}
-
/*
* We can use these to temporarily drop into
* "lazy TLB" mode and back.
@@ -378,7 +370,6 @@
&& !capable(CAP_KILL))
current->exit_signal = SIGCHLD;
- notify_parent(current, current->exit_signal);
/*
* This loop does two things:
@@ -390,6 +381,7 @@
*/
write_lock_irq(&tasklist_lock);
+ do_notify_parent(current, current->exit_signal);
while (current->p_cptr != NULL) {
p = current->p_cptr;
current->p_cptr = p->p_osptr;
@@ -402,7 +394,7 @@
p->p_osptr->p_ysptr = p;
p->p_pptr->p_cptr = p;
if (p->state == TASK_ZOMBIE)
- notify_parent(p, p->exit_signal);
+ do_notify_parent(p, p->exit_signal);
/*
* process group orphan check
* Case ii: Our child is in a different pgrp
@@ -449,7 +441,7 @@
__exit_mm(tsk);
__exit_files(tsk);
__exit_fs(tsk);
- __exit_sighand(tsk);
+ exit_sighand(tsk);
exit_thread();
tsk->state = TASK_ZOMBIE;
tsk->exit_code = code;
@@ -483,9 +475,9 @@
{
int flag, retval;
DECLARE_WAITQUEUE(wait, current);
- struct task_struct *p;
+ struct task_struct *tsk;
- if (options & ~(WNOHANG|WUNTRACED|__WCLONE|__WALL))
+ if (options & ~(WNOHANG|WUNTRACED|__WNOTHREAD|__WCLONE|__WALL))
return -EINVAL;
add_wait_queue(¤t->wait_chldexit,&wait);
@@ -493,27 +485,30 @@
flag = 0;
current->state = TASK_INTERRUPTIBLE;
read_lock(&tasklist_lock);
- for (p = current->p_cptr ; p ; p = p->p_osptr) {
- if (pid>0) {
- if (p->pid != pid)
- continue;
- } else if (!pid) {
- if (p->pgrp != current->pgrp)
- continue;
- } else if (pid != -1) {
- if (p->pgrp != -pid)
+ tsk = current;
+ do {
+ struct task_struct *p;
+ for (p = tsk->p_cptr ; p ; p = p->p_osptr) {
+ if (pid>0) {
+ if (p->pid != pid)
+ continue;
+ } else if (!pid) {
+ if (p->pgrp != current->pgrp)
+ continue;
+ } else if (pid != -1) {
+ if (p->pgrp != -pid)
+ continue;
+ }
+ /* Wait for all children (clone and not) if __WALL is set;
+ * otherwise, wait for clone children *only* if __WCLONE is
+ * set; otherwise, wait for non-clone children *only*. (Note:
+ * A "clone" child here is one that reports to its parent
+ * using a signal other than SIGCHLD.) */
+ if (((p->exit_signal != SIGCHLD) ^ ((options & __WCLONE) != 0))
+ && !(options & __WALL))
continue;
- }
- /* Wait for all children (clone and not) if __WALL is set;
- * otherwise, wait for clone children *only* if __WCLONE is
- * set; otherwise, wait for non-clone children *only*. (Note:
- * A "clone" child here is one that reports to its parent
- * using a signal other than SIGCHLD.) */
- if (((p->exit_signal != SIGCHLD) ^ ((options & __WCLONE) != 0))
- && !(options & __WALL))
- continue;
- flag = 1;
- switch (p->state) {
+ flag = 1;
+ switch (p->state) {
case TASK_STOPPED:
if (!p->exit_code)
continue;
@@ -543,15 +538,19 @@
REMOVE_LINKS(p);
p->p_pptr = p->p_opptr;
SET_LINKS(p);
+ do_notify_parent(p, SIGCHLD);
write_unlock_irq(&tasklist_lock);
- notify_parent(p, SIGCHLD);
} else
release(p);
goto end_wait4;
default:
continue;
+ }
}
- }
+ if (options & __WNOTHREAD)
+ break;
+ tsk = next_thread(tsk);
+ } while (tsk != current);
read_unlock(&tasklist_lock);
if (flag) {
retval = 0;
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)