aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/signal.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/signal.c')
-rw-r--r--kernel/signal.c61
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 */
680static void do_notify_parent_cldstop(struct task_struct *tsk, 680static 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
1545static void 1531static void do_notify_parent_cldstop(struct task_struct *tsk, int to_self, int why)
1546do_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)
1668static void 1659static void
1669finish_stop(int stop_count) 1660finish_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
1680out:
1690 schedule(); 1681 schedule();
1691 /* 1682 /*
1692 * Now we don't run again until continued. 1683 * Now we don't run again until continued.