diff options
Diffstat (limited to 'kernel/exit.c')
| -rw-r--r-- | kernel/exit.c | 192 |
1 files changed, 134 insertions, 58 deletions
diff --git a/kernel/exit.c b/kernel/exit.c index 53872bf993fa..8f6185e69b69 100644 --- a/kernel/exit.c +++ b/kernel/exit.c | |||
| @@ -19,6 +19,7 @@ | |||
| 19 | #include <linux/acct.h> | 19 | #include <linux/acct.h> |
| 20 | #include <linux/tsacct_kern.h> | 20 | #include <linux/tsacct_kern.h> |
| 21 | #include <linux/file.h> | 21 | #include <linux/file.h> |
| 22 | #include <linux/fdtable.h> | ||
| 22 | #include <linux/binfmts.h> | 23 | #include <linux/binfmts.h> |
| 23 | #include <linux/nsproxy.h> | 24 | #include <linux/nsproxy.h> |
| 24 | #include <linux/pid_namespace.h> | 25 | #include <linux/pid_namespace.h> |
| @@ -52,6 +53,11 @@ | |||
| 52 | 53 | ||
| 53 | static void exit_mm(struct task_struct * tsk); | 54 | static void exit_mm(struct task_struct * tsk); |
| 54 | 55 | ||
| 56 | static inline int task_detached(struct task_struct *p) | ||
| 57 | { | ||
| 58 | return p->exit_signal == -1; | ||
| 59 | } | ||
| 60 | |||
| 55 | static void __unhash_process(struct task_struct *p) | 61 | static void __unhash_process(struct task_struct *p) |
| 56 | { | 62 | { |
| 57 | nr_threads--; | 63 | nr_threads--; |
| @@ -120,6 +126,12 @@ static void __exit_signal(struct task_struct *tsk) | |||
| 120 | 126 | ||
| 121 | __unhash_process(tsk); | 127 | __unhash_process(tsk); |
| 122 | 128 | ||
| 129 | /* | ||
| 130 | * Do this under ->siglock, we can race with another thread | ||
| 131 | * doing sigqueue_free() if we have SIGQUEUE_PREALLOC signals. | ||
| 132 | */ | ||
| 133 | flush_sigqueue(&tsk->pending); | ||
| 134 | |||
| 123 | tsk->signal = NULL; | 135 | tsk->signal = NULL; |
| 124 | tsk->sighand = NULL; | 136 | tsk->sighand = NULL; |
| 125 | spin_unlock(&sighand->siglock); | 137 | spin_unlock(&sighand->siglock); |
| @@ -127,7 +139,6 @@ static void __exit_signal(struct task_struct *tsk) | |||
| 127 | 139 | ||
| 128 | __cleanup_sighand(sighand); | 140 | __cleanup_sighand(sighand); |
| 129 | clear_tsk_thread_flag(tsk,TIF_SIGPENDING); | 141 | clear_tsk_thread_flag(tsk,TIF_SIGPENDING); |
| 130 | flush_sigqueue(&tsk->pending); | ||
| 131 | if (sig) { | 142 | if (sig) { |
| 132 | flush_sigqueue(&sig->shared_pending); | 143 | flush_sigqueue(&sig->shared_pending); |
| 133 | taskstats_tgid_free(sig); | 144 | taskstats_tgid_free(sig); |
| @@ -160,7 +171,7 @@ repeat: | |||
| 160 | zap_leader = 0; | 171 | zap_leader = 0; |
| 161 | leader = p->group_leader; | 172 | leader = p->group_leader; |
| 162 | if (leader != p && thread_group_empty(leader) && leader->exit_state == EXIT_ZOMBIE) { | 173 | if (leader != p && thread_group_empty(leader) && leader->exit_state == EXIT_ZOMBIE) { |
| 163 | BUG_ON(leader->exit_signal == -1); | 174 | BUG_ON(task_detached(leader)); |
| 164 | do_notify_parent(leader, leader->exit_signal); | 175 | do_notify_parent(leader, leader->exit_signal); |
| 165 | /* | 176 | /* |
| 166 | * If we were the last child thread and the leader has | 177 | * If we were the last child thread and the leader has |
| @@ -170,7 +181,7 @@ repeat: | |||
| 170 | * do_notify_parent() will have marked it self-reaping in | 181 | * do_notify_parent() will have marked it self-reaping in |
| 171 | * that case. | 182 | * that case. |
| 172 | */ | 183 | */ |
| 173 | zap_leader = (leader->exit_signal == -1); | 184 | zap_leader = task_detached(leader); |
| 174 | } | 185 | } |
| 175 | 186 | ||
| 176 | write_unlock_irq(&tasklist_lock); | 187 | write_unlock_irq(&tasklist_lock); |
| @@ -329,13 +340,11 @@ void __set_special_pids(struct pid *pid) | |||
| 329 | pid_t nr = pid_nr(pid); | 340 | pid_t nr = pid_nr(pid); |
| 330 | 341 | ||
| 331 | if (task_session(curr) != pid) { | 342 | if (task_session(curr) != pid) { |
| 332 | detach_pid(curr, PIDTYPE_SID); | 343 | change_pid(curr, PIDTYPE_SID, pid); |
| 333 | attach_pid(curr, PIDTYPE_SID, pid); | ||
| 334 | set_task_session(curr, nr); | 344 | set_task_session(curr, nr); |
| 335 | } | 345 | } |
| 336 | if (task_pgrp(curr) != pid) { | 346 | if (task_pgrp(curr) != pid) { |
| 337 | detach_pid(curr, PIDTYPE_PGID); | 347 | change_pid(curr, PIDTYPE_PGID, pid); |
| 338 | attach_pid(curr, PIDTYPE_PGID, pid); | ||
| 339 | set_task_pgrp(curr, nr); | 348 | set_task_pgrp(curr, nr); |
| 340 | } | 349 | } |
| 341 | } | 350 | } |
| @@ -507,10 +516,9 @@ void put_files_struct(struct files_struct *files) | |||
| 507 | } | 516 | } |
| 508 | } | 517 | } |
| 509 | 518 | ||
| 510 | EXPORT_SYMBOL(put_files_struct); | 519 | void reset_files_struct(struct files_struct *files) |
| 511 | |||
| 512 | void reset_files_struct(struct task_struct *tsk, struct files_struct *files) | ||
| 513 | { | 520 | { |
| 521 | struct task_struct *tsk = current; | ||
| 514 | struct files_struct *old; | 522 | struct files_struct *old; |
| 515 | 523 | ||
| 516 | old = tsk->files; | 524 | old = tsk->files; |
| @@ -519,9 +527,8 @@ void reset_files_struct(struct task_struct *tsk, struct files_struct *files) | |||
| 519 | task_unlock(tsk); | 527 | task_unlock(tsk); |
| 520 | put_files_struct(old); | 528 | put_files_struct(old); |
| 521 | } | 529 | } |
| 522 | EXPORT_SYMBOL(reset_files_struct); | ||
| 523 | 530 | ||
| 524 | static void __exit_files(struct task_struct *tsk) | 531 | void exit_files(struct task_struct *tsk) |
| 525 | { | 532 | { |
| 526 | struct files_struct * files = tsk->files; | 533 | struct files_struct * files = tsk->files; |
| 527 | 534 | ||
| @@ -533,12 +540,7 @@ static void __exit_files(struct task_struct *tsk) | |||
| 533 | } | 540 | } |
| 534 | } | 541 | } |
| 535 | 542 | ||
| 536 | void exit_files(struct task_struct *tsk) | 543 | void put_fs_struct(struct fs_struct *fs) |
| 537 | { | ||
| 538 | __exit_files(tsk); | ||
| 539 | } | ||
| 540 | |||
| 541 | static void __put_fs_struct(struct fs_struct *fs) | ||
| 542 | { | 544 | { |
| 543 | /* No need to hold fs->lock if we are killing it */ | 545 | /* No need to hold fs->lock if we are killing it */ |
| 544 | if (atomic_dec_and_test(&fs->count)) { | 546 | if (atomic_dec_and_test(&fs->count)) { |
| @@ -550,12 +552,7 @@ static void __put_fs_struct(struct fs_struct *fs) | |||
| 550 | } | 552 | } |
| 551 | } | 553 | } |
| 552 | 554 | ||
| 553 | void put_fs_struct(struct fs_struct *fs) | 555 | void exit_fs(struct task_struct *tsk) |
| 554 | { | ||
| 555 | __put_fs_struct(fs); | ||
| 556 | } | ||
| 557 | |||
| 558 | static void __exit_fs(struct task_struct *tsk) | ||
| 559 | { | 556 | { |
| 560 | struct fs_struct * fs = tsk->fs; | 557 | struct fs_struct * fs = tsk->fs; |
| 561 | 558 | ||
| @@ -563,16 +560,93 @@ static void __exit_fs(struct task_struct *tsk) | |||
| 563 | task_lock(tsk); | 560 | task_lock(tsk); |
| 564 | tsk->fs = NULL; | 561 | tsk->fs = NULL; |
| 565 | task_unlock(tsk); | 562 | task_unlock(tsk); |
| 566 | __put_fs_struct(fs); | 563 | put_fs_struct(fs); |
| 567 | } | 564 | } |
| 568 | } | 565 | } |
| 569 | 566 | ||
| 570 | void exit_fs(struct task_struct *tsk) | 567 | EXPORT_SYMBOL_GPL(exit_fs); |
| 568 | |||
| 569 | #ifdef CONFIG_MM_OWNER | ||
| 570 | /* | ||
| 571 | * Task p is exiting and it owned mm, lets find a new owner for it | ||
| 572 | */ | ||
| 573 | static inline int | ||
| 574 | mm_need_new_owner(struct mm_struct *mm, struct task_struct *p) | ||
| 571 | { | 575 | { |
| 572 | __exit_fs(tsk); | 576 | /* |
| 577 | * If there are other users of the mm and the owner (us) is exiting | ||
| 578 | * we need to find a new owner to take on the responsibility. | ||
| 579 | */ | ||
| 580 | if (!mm) | ||
| 581 | return 0; | ||
| 582 | if (atomic_read(&mm->mm_users) <= 1) | ||
| 583 | return 0; | ||
| 584 | if (mm->owner != p) | ||
| 585 | return 0; | ||
| 586 | return 1; | ||
| 573 | } | 587 | } |
| 574 | 588 | ||
| 575 | EXPORT_SYMBOL_GPL(exit_fs); | 589 | void mm_update_next_owner(struct mm_struct *mm) |
| 590 | { | ||
| 591 | struct task_struct *c, *g, *p = current; | ||
| 592 | |||
| 593 | retry: | ||
| 594 | if (!mm_need_new_owner(mm, p)) | ||
| 595 | return; | ||
| 596 | |||
| 597 | read_lock(&tasklist_lock); | ||
| 598 | /* | ||
| 599 | * Search in the children | ||
| 600 | */ | ||
| 601 | list_for_each_entry(c, &p->children, sibling) { | ||
| 602 | if (c->mm == mm) | ||
| 603 | goto assign_new_owner; | ||
| 604 | } | ||
| 605 | |||
| 606 | /* | ||
| 607 | * Search in the siblings | ||
| 608 | */ | ||
| 609 | list_for_each_entry(c, &p->parent->children, sibling) { | ||
| 610 | if (c->mm == mm) | ||
| 611 | goto assign_new_owner; | ||
| 612 | } | ||
| 613 | |||
| 614 | /* | ||
| 615 | * Search through everything else. We should not get | ||
| 616 | * here often | ||
| 617 | */ | ||
| 618 | do_each_thread(g, c) { | ||
| 619 | if (c->mm == mm) | ||
| 620 | goto assign_new_owner; | ||
| 621 | } while_each_thread(g, c); | ||
| 622 | |||
| 623 | read_unlock(&tasklist_lock); | ||
| 624 | return; | ||
| 625 | |||
| 626 | assign_new_owner: | ||
| 627 | BUG_ON(c == p); | ||
| 628 | get_task_struct(c); | ||
| 629 | /* | ||
| 630 | * The task_lock protects c->mm from changing. | ||
| 631 | * We always want mm->owner->mm == mm | ||
| 632 | */ | ||
| 633 | task_lock(c); | ||
| 634 | /* | ||
| 635 | * Delay read_unlock() till we have the task_lock() | ||
| 636 | * to ensure that c does not slip away underneath us | ||
| 637 | */ | ||
| 638 | read_unlock(&tasklist_lock); | ||
| 639 | if (c->mm != mm) { | ||
| 640 | task_unlock(c); | ||
| 641 | put_task_struct(c); | ||
| 642 | goto retry; | ||
| 643 | } | ||
| 644 | cgroup_mm_owner_callbacks(mm->owner, c); | ||
| 645 | mm->owner = c; | ||
| 646 | task_unlock(c); | ||
| 647 | put_task_struct(c); | ||
| 648 | } | ||
| 649 | #endif /* CONFIG_MM_OWNER */ | ||
| 576 | 650 | ||
| 577 | /* | 651 | /* |
| 578 | * Turn us into a lazy TLB process if we | 652 | * Turn us into a lazy TLB process if we |
| @@ -613,6 +687,7 @@ static void exit_mm(struct task_struct * tsk) | |||
| 613 | /* We don't want this task to be frozen prematurely */ | 687 | /* We don't want this task to be frozen prematurely */ |
| 614 | clear_freeze_flag(tsk); | 688 | clear_freeze_flag(tsk); |
| 615 | task_unlock(tsk); | 689 | task_unlock(tsk); |
| 690 | mm_update_next_owner(mm); | ||
| 616 | mmput(mm); | 691 | mmput(mm); |
| 617 | } | 692 | } |
| 618 | 693 | ||
| @@ -627,7 +702,7 @@ reparent_thread(struct task_struct *p, struct task_struct *father, int traced) | |||
| 627 | if (unlikely(traced)) { | 702 | if (unlikely(traced)) { |
| 628 | /* Preserve ptrace links if someone else is tracing this child. */ | 703 | /* Preserve ptrace links if someone else is tracing this child. */ |
| 629 | list_del_init(&p->ptrace_list); | 704 | list_del_init(&p->ptrace_list); |
| 630 | if (p->parent != p->real_parent) | 705 | if (ptrace_reparented(p)) |
| 631 | list_add(&p->ptrace_list, &p->real_parent->ptrace_children); | 706 | list_add(&p->ptrace_list, &p->real_parent->ptrace_children); |
| 632 | } else { | 707 | } else { |
| 633 | /* If this child is being traced, then we're the one tracing it | 708 | /* If this child is being traced, then we're the one tracing it |
| @@ -651,18 +726,18 @@ reparent_thread(struct task_struct *p, struct task_struct *father, int traced) | |||
| 651 | /* If this is a threaded reparent there is no need to | 726 | /* If this is a threaded reparent there is no need to |
| 652 | * notify anyone anything has happened. | 727 | * notify anyone anything has happened. |
| 653 | */ | 728 | */ |
| 654 | if (p->real_parent->group_leader == father->group_leader) | 729 | if (same_thread_group(p->real_parent, father)) |
| 655 | return; | 730 | return; |
| 656 | 731 | ||
| 657 | /* We don't want people slaying init. */ | 732 | /* We don't want people slaying init. */ |
| 658 | if (p->exit_signal != -1) | 733 | if (!task_detached(p)) |
| 659 | p->exit_signal = SIGCHLD; | 734 | p->exit_signal = SIGCHLD; |
| 660 | 735 | ||
| 661 | /* If we'd notified the old parent about this child's death, | 736 | /* If we'd notified the old parent about this child's death, |
| 662 | * also notify the new parent. | 737 | * also notify the new parent. |
| 663 | */ | 738 | */ |
| 664 | if (!traced && p->exit_state == EXIT_ZOMBIE && | 739 | if (!traced && p->exit_state == EXIT_ZOMBIE && |
| 665 | p->exit_signal != -1 && thread_group_empty(p)) | 740 | !task_detached(p) && thread_group_empty(p)) |
| 666 | do_notify_parent(p, p->exit_signal); | 741 | do_notify_parent(p, p->exit_signal); |
| 667 | 742 | ||
| 668 | kill_orphaned_pgrp(p, father); | 743 | kill_orphaned_pgrp(p, father); |
| @@ -715,18 +790,18 @@ static void forget_original_parent(struct task_struct *father) | |||
| 715 | } else { | 790 | } else { |
| 716 | /* reparent ptraced task to its real parent */ | 791 | /* reparent ptraced task to its real parent */ |
| 717 | __ptrace_unlink (p); | 792 | __ptrace_unlink (p); |
| 718 | if (p->exit_state == EXIT_ZOMBIE && p->exit_signal != -1 && | 793 | if (p->exit_state == EXIT_ZOMBIE && !task_detached(p) && |
| 719 | thread_group_empty(p)) | 794 | thread_group_empty(p)) |
| 720 | do_notify_parent(p, p->exit_signal); | 795 | do_notify_parent(p, p->exit_signal); |
| 721 | } | 796 | } |
| 722 | 797 | ||
| 723 | /* | 798 | /* |
| 724 | * if the ptraced child is a zombie with exit_signal == -1 | 799 | * if the ptraced child is a detached zombie we must collect |
| 725 | * we must collect it before we exit, or it will remain | 800 | * it before we exit, or it will remain zombie forever since |
| 726 | * zombie forever since we prevented it from self-reap itself | 801 | * we prevented it from self-reap itself while it was being |
| 727 | * while it was being traced by us, to be able to see it in wait4. | 802 | * traced by us, to be able to see it in wait4. |
| 728 | */ | 803 | */ |
| 729 | if (unlikely(ptrace && p->exit_state == EXIT_ZOMBIE && p->exit_signal == -1)) | 804 | if (unlikely(ptrace && p->exit_state == EXIT_ZOMBIE && task_detached(p))) |
| 730 | list_add(&p->ptrace_list, &ptrace_dead); | 805 | list_add(&p->ptrace_list, &ptrace_dead); |
| 731 | } | 806 | } |
| 732 | 807 | ||
| @@ -783,29 +858,30 @@ static void exit_notify(struct task_struct *tsk, int group_dead) | |||
| 783 | * we have changed execution domain as these two values started | 858 | * we have changed execution domain as these two values started |
| 784 | * the same after a fork. | 859 | * the same after a fork. |
| 785 | */ | 860 | */ |
| 786 | if (tsk->exit_signal != SIGCHLD && tsk->exit_signal != -1 && | 861 | if (tsk->exit_signal != SIGCHLD && !task_detached(tsk) && |
| 787 | (tsk->parent_exec_id != tsk->real_parent->self_exec_id || | 862 | (tsk->parent_exec_id != tsk->real_parent->self_exec_id || |
| 788 | tsk->self_exec_id != tsk->parent_exec_id) | 863 | tsk->self_exec_id != tsk->parent_exec_id) && |
| 789 | && !capable(CAP_KILL)) | 864 | !capable(CAP_KILL)) |
| 790 | tsk->exit_signal = SIGCHLD; | 865 | tsk->exit_signal = SIGCHLD; |
| 791 | 866 | ||
| 792 | |||
| 793 | /* If something other than our normal parent is ptracing us, then | 867 | /* If something other than our normal parent is ptracing us, then |
| 794 | * send it a SIGCHLD instead of honoring exit_signal. exit_signal | 868 | * send it a SIGCHLD instead of honoring exit_signal. exit_signal |
| 795 | * only has special meaning to our real parent. | 869 | * only has special meaning to our real parent. |
| 796 | */ | 870 | */ |
| 797 | if (tsk->exit_signal != -1 && thread_group_empty(tsk)) { | 871 | if (!task_detached(tsk) && thread_group_empty(tsk)) { |
| 798 | int signal = tsk->parent == tsk->real_parent ? tsk->exit_signal : SIGCHLD; | 872 | int signal = ptrace_reparented(tsk) ? |
| 873 | SIGCHLD : tsk->exit_signal; | ||
| 799 | do_notify_parent(tsk, signal); | 874 | do_notify_parent(tsk, signal); |
| 800 | } else if (tsk->ptrace) { | 875 | } else if (tsk->ptrace) { |
| 801 | do_notify_parent(tsk, SIGCHLD); | 876 | do_notify_parent(tsk, SIGCHLD); |
| 802 | } | 877 | } |
| 803 | 878 | ||
| 804 | state = EXIT_ZOMBIE; | 879 | state = EXIT_ZOMBIE; |
| 805 | if (tsk->exit_signal == -1 && likely(!tsk->ptrace)) | 880 | if (task_detached(tsk) && likely(!tsk->ptrace)) |
| 806 | state = EXIT_DEAD; | 881 | state = EXIT_DEAD; |
| 807 | tsk->exit_state = state; | 882 | tsk->exit_state = state; |
| 808 | 883 | ||
| 884 | /* mt-exec, de_thread() is waiting for us */ | ||
| 809 | if (thread_group_leader(tsk) && | 885 | if (thread_group_leader(tsk) && |
| 810 | tsk->signal->notify_count < 0 && | 886 | tsk->signal->notify_count < 0 && |
| 811 | tsk->signal->group_exit_task) | 887 | tsk->signal->group_exit_task) |
| @@ -967,8 +1043,8 @@ NORET_TYPE void do_exit(long code) | |||
| 967 | if (group_dead) | 1043 | if (group_dead) |
| 968 | acct_process(); | 1044 | acct_process(); |
| 969 | exit_sem(tsk); | 1045 | exit_sem(tsk); |
| 970 | __exit_files(tsk); | 1046 | exit_files(tsk); |
| 971 | __exit_fs(tsk); | 1047 | exit_fs(tsk); |
| 972 | check_stack_usage(); | 1048 | check_stack_usage(); |
| 973 | exit_thread(); | 1049 | exit_thread(); |
| 974 | cgroup_exit(tsk, 1); | 1050 | cgroup_exit(tsk, 1); |
| @@ -984,7 +1060,7 @@ NORET_TYPE void do_exit(long code) | |||
| 984 | proc_exit_connector(tsk); | 1060 | proc_exit_connector(tsk); |
| 985 | exit_notify(tsk, group_dead); | 1061 | exit_notify(tsk, group_dead); |
| 986 | #ifdef CONFIG_NUMA | 1062 | #ifdef CONFIG_NUMA |
| 987 | mpol_free(tsk->mempolicy); | 1063 | mpol_put(tsk->mempolicy); |
| 988 | tsk->mempolicy = NULL; | 1064 | tsk->mempolicy = NULL; |
| 989 | #endif | 1065 | #endif |
| 990 | #ifdef CONFIG_FUTEX | 1066 | #ifdef CONFIG_FUTEX |
| @@ -1049,12 +1125,13 @@ asmlinkage long sys_exit(int error_code) | |||
| 1049 | NORET_TYPE void | 1125 | NORET_TYPE void |
| 1050 | do_group_exit(int exit_code) | 1126 | do_group_exit(int exit_code) |
| 1051 | { | 1127 | { |
| 1128 | struct signal_struct *sig = current->signal; | ||
| 1129 | |||
| 1052 | BUG_ON(exit_code & 0x80); /* core dumps don't get here */ | 1130 | BUG_ON(exit_code & 0x80); /* core dumps don't get here */ |
| 1053 | 1131 | ||
| 1054 | if (current->signal->flags & SIGNAL_GROUP_EXIT) | 1132 | if (signal_group_exit(sig)) |
| 1055 | exit_code = current->signal->group_exit_code; | 1133 | exit_code = sig->group_exit_code; |
| 1056 | else if (!thread_group_empty(current)) { | 1134 | else if (!thread_group_empty(current)) { |
| 1057 | struct signal_struct *const sig = current->signal; | ||
| 1058 | struct sighand_struct *const sighand = current->sighand; | 1135 | struct sighand_struct *const sighand = current->sighand; |
| 1059 | spin_lock_irq(&sighand->siglock); | 1136 | spin_lock_irq(&sighand->siglock); |
| 1060 | if (signal_group_exit(sig)) | 1137 | if (signal_group_exit(sig)) |
| @@ -1106,7 +1183,7 @@ static int eligible_child(enum pid_type type, struct pid *pid, int options, | |||
| 1106 | * Do not consider detached threads that are | 1183 | * Do not consider detached threads that are |
| 1107 | * not ptraced: | 1184 | * not ptraced: |
| 1108 | */ | 1185 | */ |
| 1109 | if (p->exit_signal == -1 && !p->ptrace) | 1186 | if (task_detached(p) && !p->ptrace) |
| 1110 | return 0; | 1187 | return 0; |
| 1111 | 1188 | ||
| 1112 | /* Wait for all children (clone and not) if __WALL is set; | 1189 | /* Wait for all children (clone and not) if __WALL is set; |
| @@ -1196,8 +1273,7 @@ static int wait_task_zombie(struct task_struct *p, int noreap, | |||
| 1196 | return 0; | 1273 | return 0; |
| 1197 | } | 1274 | } |
| 1198 | 1275 | ||
| 1199 | /* traced means p->ptrace, but not vice versa */ | 1276 | traced = ptrace_reparented(p); |
| 1200 | traced = (p->real_parent != p->parent); | ||
| 1201 | 1277 | ||
| 1202 | if (likely(!traced)) { | 1278 | if (likely(!traced)) { |
| 1203 | struct signal_struct *psig; | 1279 | struct signal_struct *psig; |
| @@ -1298,9 +1374,9 @@ static int wait_task_zombie(struct task_struct *p, int noreap, | |||
| 1298 | * If it's still not detached after that, don't release | 1374 | * If it's still not detached after that, don't release |
| 1299 | * it now. | 1375 | * it now. |
| 1300 | */ | 1376 | */ |
| 1301 | if (p->exit_signal != -1) { | 1377 | if (!task_detached(p)) { |
| 1302 | do_notify_parent(p, p->exit_signal); | 1378 | do_notify_parent(p, p->exit_signal); |
| 1303 | if (p->exit_signal != -1) { | 1379 | if (!task_detached(p)) { |
| 1304 | p->exit_state = EXIT_ZOMBIE; | 1380 | p->exit_state = EXIT_ZOMBIE; |
| 1305 | p = NULL; | 1381 | p = NULL; |
| 1306 | } | 1382 | } |
| @@ -1608,7 +1684,7 @@ asmlinkage long sys_waitid(int which, pid_t upid, | |||
| 1608 | put_pid(pid); | 1684 | put_pid(pid); |
| 1609 | 1685 | ||
| 1610 | /* avoid REGPARM breakage on x86: */ | 1686 | /* avoid REGPARM breakage on x86: */ |
| 1611 | prevent_tail_call(ret); | 1687 | asmlinkage_protect(5, ret, which, upid, infop, options, ru); |
| 1612 | return ret; | 1688 | return ret; |
| 1613 | } | 1689 | } |
| 1614 | 1690 | ||
| @@ -1640,7 +1716,7 @@ asmlinkage long sys_wait4(pid_t upid, int __user *stat_addr, | |||
| 1640 | put_pid(pid); | 1716 | put_pid(pid); |
| 1641 | 1717 | ||
| 1642 | /* avoid REGPARM breakage on x86: */ | 1718 | /* avoid REGPARM breakage on x86: */ |
| 1643 | prevent_tail_call(ret); | 1719 | asmlinkage_protect(4, ret, upid, stat_addr, options, ru); |
| 1644 | return ret; | 1720 | return ret; |
| 1645 | } | 1721 | } |
| 1646 | 1722 | ||
