diff options
Diffstat (limited to 'kernel/exit.c')
| -rw-r--r-- | kernel/exit.c | 40 |
1 files changed, 19 insertions, 21 deletions
diff --git a/kernel/exit.c b/kernel/exit.c index 1143012951e9..546774a31a66 100644 --- a/kernel/exit.c +++ b/kernel/exit.c | |||
| @@ -68,10 +68,10 @@ static void __unhash_process(struct task_struct *p) | |||
| 68 | detach_pid(p, PIDTYPE_SID); | 68 | detach_pid(p, PIDTYPE_SID); |
| 69 | 69 | ||
| 70 | list_del_rcu(&p->tasks); | 70 | list_del_rcu(&p->tasks); |
| 71 | list_del_init(&p->sibling); | ||
| 71 | __get_cpu_var(process_counts)--; | 72 | __get_cpu_var(process_counts)--; |
| 72 | } | 73 | } |
| 73 | list_del_rcu(&p->thread_group); | 74 | list_del_rcu(&p->thread_group); |
| 74 | list_del_init(&p->sibling); | ||
| 75 | } | 75 | } |
| 76 | 76 | ||
| 77 | /* | 77 | /* |
| @@ -736,12 +736,9 @@ static struct task_struct *find_new_reaper(struct task_struct *father) | |||
| 736 | /* | 736 | /* |
| 737 | * Any that need to be release_task'd are put on the @dead list. | 737 | * Any that need to be release_task'd are put on the @dead list. |
| 738 | */ | 738 | */ |
| 739 | static void reparent_thread(struct task_struct *father, struct task_struct *p, | 739 | static void reparent_leader(struct task_struct *father, struct task_struct *p, |
| 740 | struct list_head *dead) | 740 | struct list_head *dead) |
| 741 | { | 741 | { |
| 742 | if (p->pdeath_signal) | ||
| 743 | group_send_sig_info(p->pdeath_signal, SEND_SIG_NOINFO, p); | ||
| 744 | |||
| 745 | list_move_tail(&p->sibling, &p->real_parent->children); | 742 | list_move_tail(&p->sibling, &p->real_parent->children); |
| 746 | 743 | ||
| 747 | if (task_detached(p)) | 744 | if (task_detached(p)) |
| @@ -780,12 +777,18 @@ static void forget_original_parent(struct task_struct *father) | |||
| 780 | reaper = find_new_reaper(father); | 777 | reaper = find_new_reaper(father); |
| 781 | 778 | ||
| 782 | list_for_each_entry_safe(p, n, &father->children, sibling) { | 779 | list_for_each_entry_safe(p, n, &father->children, sibling) { |
| 783 | p->real_parent = reaper; | 780 | struct task_struct *t = p; |
| 784 | if (p->parent == father) { | 781 | do { |
| 785 | BUG_ON(task_ptrace(p)); | 782 | t->real_parent = reaper; |
| 786 | p->parent = p->real_parent; | 783 | if (t->parent == father) { |
| 787 | } | 784 | BUG_ON(task_ptrace(t)); |
| 788 | reparent_thread(father, p, &dead_children); | 785 | t->parent = t->real_parent; |
| 786 | } | ||
| 787 | if (t->pdeath_signal) | ||
| 788 | group_send_sig_info(t->pdeath_signal, | ||
| 789 | SEND_SIG_NOINFO, t); | ||
| 790 | } while_each_thread(p, t); | ||
| 791 | reparent_leader(father, p, &dead_children); | ||
| 789 | } | 792 | } |
| 790 | write_unlock_irq(&tasklist_lock); | 793 | write_unlock_irq(&tasklist_lock); |
| 791 | 794 | ||
| @@ -933,7 +936,7 @@ NORET_TYPE void do_exit(long code) | |||
| 933 | * an exiting task cleaning up the robust pi futexes. | 936 | * an exiting task cleaning up the robust pi futexes. |
| 934 | */ | 937 | */ |
| 935 | smp_mb(); | 938 | smp_mb(); |
| 936 | spin_unlock_wait(&tsk->pi_lock); | 939 | raw_spin_unlock_wait(&tsk->pi_lock); |
| 937 | 940 | ||
| 938 | if (unlikely(in_atomic())) | 941 | if (unlikely(in_atomic())) |
| 939 | printk(KERN_INFO "note: %s[%d] exited with preempt_count %d\n", | 942 | printk(KERN_INFO "note: %s[%d] exited with preempt_count %d\n", |
| @@ -971,7 +974,7 @@ NORET_TYPE void do_exit(long code) | |||
| 971 | exit_thread(); | 974 | exit_thread(); |
| 972 | cgroup_exit(tsk, 1); | 975 | cgroup_exit(tsk, 1); |
| 973 | 976 | ||
| 974 | if (group_dead && tsk->signal->leader) | 977 | if (group_dead) |
| 975 | disassociate_ctty(1); | 978 | disassociate_ctty(1); |
| 976 | 979 | ||
| 977 | module_put(task_thread_info(tsk)->exec_domain->module); | 980 | module_put(task_thread_info(tsk)->exec_domain->module); |
| @@ -1551,14 +1554,9 @@ static int do_wait_thread(struct wait_opts *wo, struct task_struct *tsk) | |||
| 1551 | struct task_struct *p; | 1554 | struct task_struct *p; |
| 1552 | 1555 | ||
| 1553 | list_for_each_entry(p, &tsk->children, sibling) { | 1556 | list_for_each_entry(p, &tsk->children, sibling) { |
| 1554 | /* | 1557 | int ret = wait_consider_task(wo, 0, p); |
| 1555 | * Do not consider detached threads. | 1558 | if (ret) |
| 1556 | */ | 1559 | return ret; |
| 1557 | if (!task_detached(p)) { | ||
| 1558 | int ret = wait_consider_task(wo, 0, p); | ||
| 1559 | if (ret) | ||
| 1560 | return ret; | ||
| 1561 | } | ||
| 1562 | } | 1560 | } |
| 1563 | 1561 | ||
| 1564 | return 0; | 1562 | return 0; |
