aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/exit.c
diff options
context:
space:
mode:
authorOleg Nesterov <oleg@redhat.com>2014-12-10 18:55:20 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2014-12-10 20:41:18 -0500
commit482a3767e5087f6e6ad2486a6655aaa5f3d59301 (patch)
tree53e54ff3b94db9a691f413684e27612347dbce96 /kernel/exit.c
parentad9e206aefa56788b676ebcd6329e828f40d2238 (diff)
exit: reparent: call forget_original_parent() under tasklist_lock
Shift "release dead children" loop from forget_original_parent() to its caller, exit_notify(). It is safe to reap them even if our parent reaps us right after we drop tasklist_lock, those children no longer have any connection to the exiting task. And this allows us to avoid write_lock_irq(tasklist_lock) right after it was released by forget_original_parent(), we can simply call it with tasklist_lock held. While at it, move the comment about forget_original_parent() up to this function. Signed-off-by: Oleg Nesterov <oleg@redhat.com> Cc: Aaron Tomlin <atomlin@redhat.com> Cc: "Eric W. Biederman" <ebiederm@xmission.com> Cc: Sterling Alexander <stalexan@redhat.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'kernel/exit.c')
-rw-r--r--kernel/exit.c47
1 files changed, 23 insertions, 24 deletions
diff --git a/kernel/exit.c b/kernel/exit.c
index 063745699f7f..8061891ddd9b 100644
--- a/kernel/exit.c
+++ b/kernel/exit.c
@@ -560,19 +560,26 @@ static void reparent_leader(struct task_struct *father, struct task_struct *p,
560 kill_orphaned_pgrp(p, father); 560 kill_orphaned_pgrp(p, father);
561} 561}
562 562
563static void forget_original_parent(struct task_struct *father) 563/*
564 * This does two things:
565 *
566 * A. Make init inherit all the child processes
567 * B. Check to see if any process groups have become orphaned
568 * as a result of our exiting, and if they have any stopped
569 * jobs, send them a SIGHUP and then a SIGCONT. (POSIX 3.2.2.2)
570 */
571static void forget_original_parent(struct task_struct *father,
572 struct list_head *dead)
564{ 573{
565 struct task_struct *p, *t, *n, *reaper; 574 struct task_struct *p, *t, *reaper;
566 LIST_HEAD(dead_children);
567 575
568 write_lock_irq(&tasklist_lock);
569 if (unlikely(!list_empty(&father->ptraced))) 576 if (unlikely(!list_empty(&father->ptraced)))
570 exit_ptrace(father, &dead_children); 577 exit_ptrace(father, dead);
571 578
572 /* Can drop and reacquire tasklist_lock */ 579 /* Can drop and reacquire tasklist_lock */
573 reaper = find_child_reaper(father); 580 reaper = find_child_reaper(father);
574 if (list_empty(&father->children)) 581 if (list_empty(&father->children))
575 goto unlock; 582 return;
576 583
577 reaper = find_new_reaper(father, reaper); 584 reaper = find_new_reaper(father, reaper);
578 list_for_each_entry(p, &father->children, sibling) { 585 list_for_each_entry(p, &father->children, sibling) {
@@ -590,16 +597,9 @@ static void forget_original_parent(struct task_struct *father)
590 * notify anyone anything has happened. 597 * notify anyone anything has happened.
591 */ 598 */
592 if (!same_thread_group(reaper, father)) 599 if (!same_thread_group(reaper, father))
593 reparent_leader(father, p, &dead_children); 600 reparent_leader(father, p, dead);
594 } 601 }
595 list_splice_tail_init(&father->children, &reaper->children); 602 list_splice_tail_init(&father->children, &reaper->children);
596 unlock:
597 write_unlock_irq(&tasklist_lock);
598
599 list_for_each_entry_safe(p, n, &dead_children, ptrace_entry) {
600 list_del_init(&p->ptrace_entry);
601 release_task(p);
602 }
603} 603}
604 604
605/* 605/*
@@ -609,18 +609,12 @@ static void forget_original_parent(struct task_struct *father)
609static void exit_notify(struct task_struct *tsk, int group_dead) 609static void exit_notify(struct task_struct *tsk, int group_dead)
610{ 610{
611 bool autoreap; 611 bool autoreap;
612 612 struct task_struct *p, *n;
613 /* 613 LIST_HEAD(dead);
614 * This does two things:
615 *
616 * A. Make init inherit all the child processes
617 * B. Check to see if any process groups have become orphaned
618 * as a result of our exiting, and if they have any stopped
619 * jobs, send them a SIGHUP and then a SIGCONT. (POSIX 3.2.2.2)
620 */
621 forget_original_parent(tsk);
622 614
623 write_lock_irq(&tasklist_lock); 615 write_lock_irq(&tasklist_lock);
616 forget_original_parent(tsk, &dead);
617
624 if (group_dead) 618 if (group_dead)
625 kill_orphaned_pgrp(tsk->group_leader, NULL); 619 kill_orphaned_pgrp(tsk->group_leader, NULL);
626 620
@@ -644,6 +638,11 @@ static void exit_notify(struct task_struct *tsk, int group_dead)
644 wake_up_process(tsk->signal->group_exit_task); 638 wake_up_process(tsk->signal->group_exit_task);
645 write_unlock_irq(&tasklist_lock); 639 write_unlock_irq(&tasklist_lock);
646 640
641 list_for_each_entry_safe(p, n, &dead, ptrace_entry) {
642 list_del_init(&p->ptrace_entry);
643 release_task(p);
644 }
645
647 /* If the process is dead, release it - nobody will wait for it */ 646 /* If the process is dead, release it - nobody will wait for it */
648 if (autoreap) 647 if (autoreap)
649 release_task(tsk); 648 release_task(tsk);