diff options
Diffstat (limited to 'kernel/signal.c')
-rw-r--r-- | kernel/signal.c | 61 |
1 files changed, 26 insertions, 35 deletions
diff --git a/kernel/signal.c b/kernel/signal.c index d282fea81138..56e33df2b67f 100644 --- a/kernel/signal.c +++ b/kernel/signal.c | |||
@@ -678,7 +678,7 @@ static int check_kill_permission(int sig, struct siginfo *info, | |||
678 | 678 | ||
679 | /* forward decl */ | 679 | /* forward decl */ |
680 | static void do_notify_parent_cldstop(struct task_struct *tsk, | 680 | static void do_notify_parent_cldstop(struct task_struct *tsk, |
681 | struct task_struct *parent, | 681 | int to_self, |
682 | int why); | 682 | int why); |
683 | 683 | ||
684 | /* | 684 | /* |
@@ -729,14 +729,7 @@ static void handle_stop_signal(int sig, struct task_struct *p) | |||
729 | p->signal->group_stop_count = 0; | 729 | p->signal->group_stop_count = 0; |
730 | p->signal->flags = SIGNAL_STOP_CONTINUED; | 730 | p->signal->flags = SIGNAL_STOP_CONTINUED; |
731 | spin_unlock(&p->sighand->siglock); | 731 | spin_unlock(&p->sighand->siglock); |
732 | if (p->ptrace & PT_PTRACED) | 732 | do_notify_parent_cldstop(p, (p->ptrace & PT_PTRACED), CLD_STOPPED); |
733 | do_notify_parent_cldstop(p, p->parent, | ||
734 | CLD_STOPPED); | ||
735 | else | ||
736 | do_notify_parent_cldstop( | ||
737 | p->group_leader, | ||
738 | p->group_leader->real_parent, | ||
739 | CLD_STOPPED); | ||
740 | spin_lock(&p->sighand->siglock); | 733 | spin_lock(&p->sighand->siglock); |
741 | } | 734 | } |
742 | rm_from_queue(SIG_KERNEL_STOP_MASK, &p->signal->shared_pending); | 735 | rm_from_queue(SIG_KERNEL_STOP_MASK, &p->signal->shared_pending); |
@@ -777,14 +770,7 @@ static void handle_stop_signal(int sig, struct task_struct *p) | |||
777 | p->signal->flags = SIGNAL_STOP_CONTINUED; | 770 | p->signal->flags = SIGNAL_STOP_CONTINUED; |
778 | p->signal->group_exit_code = 0; | 771 | p->signal->group_exit_code = 0; |
779 | spin_unlock(&p->sighand->siglock); | 772 | spin_unlock(&p->sighand->siglock); |
780 | if (p->ptrace & PT_PTRACED) | 773 | do_notify_parent_cldstop(p, (p->ptrace & PT_PTRACED), CLD_CONTINUED); |
781 | do_notify_parent_cldstop(p, p->parent, | ||
782 | CLD_CONTINUED); | ||
783 | else | ||
784 | do_notify_parent_cldstop( | ||
785 | p->group_leader, | ||
786 | p->group_leader->real_parent, | ||
787 | CLD_CONTINUED); | ||
788 | spin_lock(&p->sighand->siglock); | 774 | spin_lock(&p->sighand->siglock); |
789 | } else { | 775 | } else { |
790 | /* | 776 | /* |
@@ -1542,14 +1528,20 @@ void do_notify_parent(struct task_struct *tsk, int sig) | |||
1542 | spin_unlock_irqrestore(&psig->siglock, flags); | 1528 | spin_unlock_irqrestore(&psig->siglock, flags); |
1543 | } | 1529 | } |
1544 | 1530 | ||
1545 | static void | 1531 | static void do_notify_parent_cldstop(struct task_struct *tsk, int to_self, int why) |
1546 | do_notify_parent_cldstop(struct task_struct *tsk, struct task_struct *parent, | ||
1547 | int why) | ||
1548 | { | 1532 | { |
1549 | struct siginfo info; | 1533 | struct siginfo info; |
1550 | unsigned long flags; | 1534 | unsigned long flags; |
1535 | struct task_struct *parent; | ||
1551 | struct sighand_struct *sighand; | 1536 | struct sighand_struct *sighand; |
1552 | 1537 | ||
1538 | if (to_self) | ||
1539 | parent = tsk->parent; | ||
1540 | else { | ||
1541 | tsk = tsk->group_leader; | ||
1542 | parent = tsk->real_parent; | ||
1543 | } | ||
1544 | |||
1553 | info.si_signo = SIGCHLD; | 1545 | info.si_signo = SIGCHLD; |
1554 | info.si_errno = 0; | 1546 | info.si_errno = 0; |
1555 | info.si_pid = tsk->pid; | 1547 | info.si_pid = tsk->pid; |
@@ -1618,8 +1610,7 @@ static void ptrace_stop(int exit_code, int nostop_code, siginfo_t *info) | |||
1618 | !(current->ptrace & PT_ATTACHED)) && | 1610 | !(current->ptrace & PT_ATTACHED)) && |
1619 | (likely(current->parent->signal != current->signal) || | 1611 | (likely(current->parent->signal != current->signal) || |
1620 | !unlikely(current->signal->flags & SIGNAL_GROUP_EXIT))) { | 1612 | !unlikely(current->signal->flags & SIGNAL_GROUP_EXIT))) { |
1621 | do_notify_parent_cldstop(current, current->parent, | 1613 | do_notify_parent_cldstop(current, 1, CLD_TRAPPED); |
1622 | CLD_TRAPPED); | ||
1623 | read_unlock(&tasklist_lock); | 1614 | read_unlock(&tasklist_lock); |
1624 | schedule(); | 1615 | schedule(); |
1625 | } else { | 1616 | } else { |
@@ -1668,25 +1659,25 @@ void ptrace_notify(int exit_code) | |||
1668 | static void | 1659 | static void |
1669 | finish_stop(int stop_count) | 1660 | finish_stop(int stop_count) |
1670 | { | 1661 | { |
1662 | int to_self; | ||
1663 | |||
1671 | /* | 1664 | /* |
1672 | * If there are no other threads in the group, or if there is | 1665 | * If there are no other threads in the group, or if there is |
1673 | * a group stop in progress and we are the last to stop, | 1666 | * a group stop in progress and we are the last to stop, |
1674 | * report to the parent. When ptraced, every thread reports itself. | 1667 | * report to the parent. When ptraced, every thread reports itself. |
1675 | */ | 1668 | */ |
1676 | if (stop_count < 0 || (current->ptrace & PT_PTRACED)) { | 1669 | if (stop_count < 0 || (current->ptrace & PT_PTRACED)) |
1677 | read_lock(&tasklist_lock); | 1670 | to_self = 1; |
1678 | do_notify_parent_cldstop(current, current->parent, | 1671 | else if (stop_count == 0) |
1679 | CLD_STOPPED); | 1672 | to_self = 0; |
1680 | read_unlock(&tasklist_lock); | 1673 | else |
1681 | } | 1674 | goto out; |
1682 | else if (stop_count == 0) { | ||
1683 | read_lock(&tasklist_lock); | ||
1684 | do_notify_parent_cldstop(current->group_leader, | ||
1685 | current->group_leader->real_parent, | ||
1686 | CLD_STOPPED); | ||
1687 | read_unlock(&tasklist_lock); | ||
1688 | } | ||
1689 | 1675 | ||
1676 | read_lock(&tasklist_lock); | ||
1677 | do_notify_parent_cldstop(current, to_self, CLD_STOPPED); | ||
1678 | read_unlock(&tasklist_lock); | ||
1679 | |||
1680 | out: | ||
1690 | schedule(); | 1681 | schedule(); |
1691 | /* | 1682 | /* |
1692 | * Now we don't run again until continued. | 1683 | * Now we don't run again until continued. |