diff options
Diffstat (limited to 'kernel/signal.c')
-rw-r--r-- | kernel/signal.c | 75 |
1 files changed, 6 insertions, 69 deletions
diff --git a/kernel/signal.c b/kernel/signal.c index 4333b6dbb424..6a5f97cd337a 100644 --- a/kernel/signal.c +++ b/kernel/signal.c | |||
@@ -911,27 +911,6 @@ __group_complete_signal(int sig, struct task_struct *p) | |||
911 | } while_each_thread(p, t); | 911 | } while_each_thread(p, t); |
912 | return; | 912 | return; |
913 | } | 913 | } |
914 | |||
915 | /* | ||
916 | * There will be a core dump. We make all threads other | ||
917 | * than the chosen one go into a group stop so that nothing | ||
918 | * happens until it gets scheduled, takes the signal off | ||
919 | * the shared queue, and does the core dump. This is a | ||
920 | * little more complicated than strictly necessary, but it | ||
921 | * keeps the signal state that winds up in the core dump | ||
922 | * unchanged from the death state, e.g. which thread had | ||
923 | * the core-dump signal unblocked. | ||
924 | */ | ||
925 | rm_from_queue(SIG_KERNEL_STOP_MASK, &t->pending); | ||
926 | rm_from_queue(SIG_KERNEL_STOP_MASK, &p->signal->shared_pending); | ||
927 | p->signal->group_stop_count = 0; | ||
928 | p->signal->group_exit_task = t; | ||
929 | p = t; | ||
930 | do { | ||
931 | p->signal->group_stop_count++; | ||
932 | signal_wake_up(t, t == p); | ||
933 | } while_each_thread(p, t); | ||
934 | return; | ||
935 | } | 914 | } |
936 | 915 | ||
937 | /* | 916 | /* |
@@ -978,7 +957,6 @@ void zap_other_threads(struct task_struct *p) | |||
978 | { | 957 | { |
979 | struct task_struct *t; | 958 | struct task_struct *t; |
980 | 959 | ||
981 | p->signal->flags = SIGNAL_GROUP_EXIT; | ||
982 | p->signal->group_stop_count = 0; | 960 | p->signal->group_stop_count = 0; |
983 | 961 | ||
984 | for (t = next_thread(p); t != p; t = next_thread(t)) { | 962 | for (t = next_thread(p); t != p; t = next_thread(t)) { |
@@ -1709,9 +1687,6 @@ static int do_signal_stop(int signr) | |||
1709 | struct signal_struct *sig = current->signal; | 1687 | struct signal_struct *sig = current->signal; |
1710 | int stop_count; | 1688 | int stop_count; |
1711 | 1689 | ||
1712 | if (!likely(sig->flags & SIGNAL_STOP_DEQUEUED)) | ||
1713 | return 0; | ||
1714 | |||
1715 | if (sig->group_stop_count > 0) { | 1690 | if (sig->group_stop_count > 0) { |
1716 | /* | 1691 | /* |
1717 | * There is a group stop in progress. We don't need to | 1692 | * There is a group stop in progress. We don't need to |
@@ -1719,12 +1694,15 @@ static int do_signal_stop(int signr) | |||
1719 | */ | 1694 | */ |
1720 | stop_count = --sig->group_stop_count; | 1695 | stop_count = --sig->group_stop_count; |
1721 | } else { | 1696 | } else { |
1697 | struct task_struct *t; | ||
1698 | |||
1699 | if (!likely(sig->flags & SIGNAL_STOP_DEQUEUED) || | ||
1700 | unlikely(sig->group_exit_task)) | ||
1701 | return 0; | ||
1722 | /* | 1702 | /* |
1723 | * There is no group stop already in progress. | 1703 | * There is no group stop already in progress. |
1724 | * We must initiate one now. | 1704 | * We must initiate one now. |
1725 | */ | 1705 | */ |
1726 | struct task_struct *t; | ||
1727 | |||
1728 | sig->group_exit_code = signr; | 1706 | sig->group_exit_code = signr; |
1729 | 1707 | ||
1730 | stop_count = 0; | 1708 | stop_count = 0; |
@@ -1752,47 +1730,6 @@ static int do_signal_stop(int signr) | |||
1752 | return 1; | 1730 | return 1; |
1753 | } | 1731 | } |
1754 | 1732 | ||
1755 | /* | ||
1756 | * Do appropriate magic when group_stop_count > 0. | ||
1757 | * We return nonzero if we stopped, after releasing the siglock. | ||
1758 | * We return zero if we still hold the siglock and should look | ||
1759 | * for another signal without checking group_stop_count again. | ||
1760 | */ | ||
1761 | static int handle_group_stop(void) | ||
1762 | { | ||
1763 | int stop_count; | ||
1764 | |||
1765 | if (current->signal->group_exit_task == current) { | ||
1766 | /* | ||
1767 | * Group stop is so we can do a core dump, | ||
1768 | * We are the initiating thread, so get on with it. | ||
1769 | */ | ||
1770 | current->signal->group_exit_task = NULL; | ||
1771 | return 0; | ||
1772 | } | ||
1773 | |||
1774 | if (current->signal->flags & SIGNAL_GROUP_EXIT) | ||
1775 | /* | ||
1776 | * Group stop is so another thread can do a core dump, | ||
1777 | * or else we are racing against a death signal. | ||
1778 | * Just punt the stop so we can get the next signal. | ||
1779 | */ | ||
1780 | return 0; | ||
1781 | |||
1782 | /* | ||
1783 | * There is a group stop in progress. We stop | ||
1784 | * without any associated signal being in our queue. | ||
1785 | */ | ||
1786 | stop_count = --current->signal->group_stop_count; | ||
1787 | if (stop_count == 0) | ||
1788 | current->signal->flags = SIGNAL_STOP_STOPPED; | ||
1789 | current->exit_code = current->signal->group_exit_code; | ||
1790 | set_current_state(TASK_STOPPED); | ||
1791 | spin_unlock_irq(¤t->sighand->siglock); | ||
1792 | finish_stop(stop_count); | ||
1793 | return 1; | ||
1794 | } | ||
1795 | |||
1796 | int get_signal_to_deliver(siginfo_t *info, struct k_sigaction *return_ka, | 1733 | int get_signal_to_deliver(siginfo_t *info, struct k_sigaction *return_ka, |
1797 | struct pt_regs *regs, void *cookie) | 1734 | struct pt_regs *regs, void *cookie) |
1798 | { | 1735 | { |
@@ -1807,7 +1744,7 @@ relock: | |||
1807 | struct k_sigaction *ka; | 1744 | struct k_sigaction *ka; |
1808 | 1745 | ||
1809 | if (unlikely(current->signal->group_stop_count > 0) && | 1746 | if (unlikely(current->signal->group_stop_count > 0) && |
1810 | handle_group_stop()) | 1747 | do_signal_stop(0)) |
1811 | goto relock; | 1748 | goto relock; |
1812 | 1749 | ||
1813 | signr = dequeue_signal(current, mask, info); | 1750 | signr = dequeue_signal(current, mask, info); |