diff options
| author | Oleg Nesterov <oleg@tv-sign.ru> | 2008-03-02 13:44:40 -0500 |
|---|---|---|
| committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2008-03-03 17:53:16 -0500 |
| commit | f49ee505b1ecb5960984880740f09aba87f870dc (patch) | |
| tree | 2ff1289ecd2741d3f9d3a298662bc9b5a6266a3d | |
| parent | 5ce2087ed0eb424e0889bdc9102727f65d2ecdde (diff) | |
introduce kill_orphaned_pgrp() helper
Factor out the common code in reparent_thread() and exit_notify().
No functional changes.
Signed-off-by: Oleg Nesterov <oleg@tv-sign.ru>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
| -rw-r--r-- | kernel/exit.c | 74 |
1 files changed, 35 insertions, 39 deletions
diff --git a/kernel/exit.c b/kernel/exit.c index 506a957b665..11fcce76015 100644 --- a/kernel/exit.c +++ b/kernel/exit.c | |||
| @@ -255,6 +255,37 @@ static int has_stopped_jobs(struct pid *pgrp) | |||
| 255 | return retval; | 255 | return retval; |
| 256 | } | 256 | } |
| 257 | 257 | ||
| 258 | /* | ||
| 259 | * Check to see if any process groups have become orphaned as | ||
| 260 | * a result of our exiting, and if they have any stopped jobs, | ||
| 261 | * send them a SIGHUP and then a SIGCONT. (POSIX 3.2.2.2) | ||
| 262 | */ | ||
| 263 | static void | ||
| 264 | kill_orphaned_pgrp(struct task_struct *tsk, struct task_struct *parent) | ||
| 265 | { | ||
| 266 | struct pid *pgrp = task_pgrp(tsk); | ||
| 267 | struct task_struct *ignored_task = tsk; | ||
| 268 | |||
| 269 | if (!parent) | ||
| 270 | /* exit: our father is in a different pgrp than | ||
| 271 | * we are and we were the only connection outside. | ||
| 272 | */ | ||
| 273 | parent = tsk->real_parent; | ||
| 274 | else | ||
| 275 | /* reparent: our child is in a different pgrp than | ||
| 276 | * we are, and it was the only connection outside. | ||
| 277 | */ | ||
| 278 | ignored_task = NULL; | ||
| 279 | |||
| 280 | if (task_pgrp(parent) != pgrp && | ||
| 281 | task_session(parent) == task_session(tsk) && | ||
| 282 | will_become_orphaned_pgrp(pgrp, ignored_task) && | ||
| 283 | has_stopped_jobs(pgrp)) { | ||
| 284 | __kill_pgrp_info(SIGHUP, SEND_SIG_PRIV, pgrp); | ||
| 285 | __kill_pgrp_info(SIGCONT, SEND_SIG_PRIV, pgrp); | ||
| 286 | } | ||
| 287 | } | ||
| 288 | |||
| 258 | /** | 289 | /** |
| 259 | * reparent_to_kthreadd - Reparent the calling kernel thread to kthreadd | 290 | * reparent_to_kthreadd - Reparent the calling kernel thread to kthreadd |
| 260 | * | 291 | * |
| @@ -635,22 +666,7 @@ reparent_thread(struct task_struct *p, struct task_struct *father, int traced) | |||
| 635 | p->exit_signal != -1 && thread_group_empty(p)) | 666 | p->exit_signal != -1 && thread_group_empty(p)) |
| 636 | do_notify_parent(p, p->exit_signal); | 667 | do_notify_parent(p, p->exit_signal); |
| 637 | 668 | ||
| 638 | /* | 669 | kill_orphaned_pgrp(p, father); |
| 639 | * process group orphan check | ||
| 640 | * Case ii: Our child is in a different pgrp | ||
| 641 | * than we are, and it was the only connection | ||
| 642 | * outside, so the child pgrp is now orphaned. | ||
| 643 | */ | ||
| 644 | if ((task_pgrp(p) != task_pgrp(father)) && | ||
| 645 | (task_session(p) == task_session(father))) { | ||
| 646 | struct pid *pgrp = task_pgrp(p); | ||
| 647 | |||
| 648 | if (will_become_orphaned_pgrp(pgrp, NULL) && | ||
| 649 | has_stopped_jobs(pgrp)) { | ||
| 650 | __kill_pgrp_info(SIGHUP, SEND_SIG_PRIV, pgrp); | ||
| 651 | __kill_pgrp_info(SIGCONT, SEND_SIG_PRIV, pgrp); | ||
| 652 | } | ||
| 653 | } | ||
| 654 | } | 670 | } |
| 655 | 671 | ||
| 656 | /* | 672 | /* |
| @@ -738,8 +754,6 @@ static void forget_original_parent(struct task_struct *father) | |||
| 738 | static void exit_notify(struct task_struct *tsk) | 754 | static void exit_notify(struct task_struct *tsk) |
| 739 | { | 755 | { |
| 740 | int state; | 756 | int state; |
| 741 | struct task_struct *t; | ||
| 742 | struct pid *pgrp; | ||
| 743 | 757 | ||
| 744 | /* | 758 | /* |
| 745 | * This does two things: | 759 | * This does two things: |
| @@ -753,25 +767,7 @@ static void exit_notify(struct task_struct *tsk) | |||
| 753 | exit_task_namespaces(tsk); | 767 | exit_task_namespaces(tsk); |
| 754 | 768 | ||
| 755 | write_lock_irq(&tasklist_lock); | 769 | write_lock_irq(&tasklist_lock); |
| 756 | /* | 770 | kill_orphaned_pgrp(tsk, NULL); |
| 757 | * Check to see if any process groups have become orphaned | ||
| 758 | * as a result of our exiting, and if they have any stopped | ||
| 759 | * jobs, send them a SIGHUP and then a SIGCONT. (POSIX 3.2.2.2) | ||
| 760 | * | ||
| 761 | * Case i: Our father is in a different pgrp than we are | ||
| 762 | * and we were the only connection outside, so our pgrp | ||
| 763 | * is about to become orphaned. | ||
| 764 | */ | ||
| 765 | t = tsk->real_parent; | ||
| 766 | |||
| 767 | pgrp = task_pgrp(tsk); | ||
| 768 | if ((task_pgrp(t) != pgrp) && | ||
| 769 | (task_session(t) == task_session(tsk)) && | ||
| 770 | will_become_orphaned_pgrp(pgrp, tsk) && | ||
| 771 | has_stopped_jobs(pgrp)) { | ||
| 772 | __kill_pgrp_info(SIGHUP, SEND_SIG_PRIV, pgrp); | ||
| 773 | __kill_pgrp_info(SIGCONT, SEND_SIG_PRIV, pgrp); | ||
| 774 | } | ||
| 775 | 771 | ||
| 776 | /* Let father know we died | 772 | /* Let father know we died |
| 777 | * | 773 | * |
| @@ -788,8 +784,8 @@ static void exit_notify(struct task_struct *tsk) | |||
| 788 | * the same after a fork. | 784 | * the same after a fork. |
| 789 | */ | 785 | */ |
| 790 | if (tsk->exit_signal != SIGCHLD && tsk->exit_signal != -1 && | 786 | if (tsk->exit_signal != SIGCHLD && tsk->exit_signal != -1 && |
| 791 | ( tsk->parent_exec_id != t->self_exec_id || | 787 | (tsk->parent_exec_id != tsk->real_parent->self_exec_id || |
| 792 | tsk->self_exec_id != tsk->parent_exec_id) | 788 | tsk->self_exec_id != tsk->parent_exec_id) |
| 793 | && !capable(CAP_KILL)) | 789 | && !capable(CAP_KILL)) |
| 794 | tsk->exit_signal = SIGCHLD; | 790 | tsk->exit_signal = SIGCHLD; |
| 795 | 791 | ||
