aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/signal.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/signal.c')
-rw-r--r--kernel/signal.c32
1 files changed, 11 insertions, 21 deletions
diff --git a/kernel/signal.c b/kernel/signal.c
index 24d5059ab0a9..0528a959daa9 100644
--- a/kernel/signal.c
+++ b/kernel/signal.c
@@ -591,9 +591,7 @@ static int check_kill_permission(int sig, struct siginfo *info,
591} 591}
592 592
593/* forward decl */ 593/* forward decl */
594static void do_notify_parent_cldstop(struct task_struct *tsk, 594static void do_notify_parent_cldstop(struct task_struct *tsk, int why);
595 int to_self,
596 int why);
597 595
598/* 596/*
599 * Handle magic process-wide effects of stop/continue signals. 597 * Handle magic process-wide effects of stop/continue signals.
@@ -643,7 +641,7 @@ static void handle_stop_signal(int sig, struct task_struct *p)
643 p->signal->group_stop_count = 0; 641 p->signal->group_stop_count = 0;
644 p->signal->flags = SIGNAL_STOP_CONTINUED; 642 p->signal->flags = SIGNAL_STOP_CONTINUED;
645 spin_unlock(&p->sighand->siglock); 643 spin_unlock(&p->sighand->siglock);
646 do_notify_parent_cldstop(p, (p->ptrace & PT_PTRACED), CLD_STOPPED); 644 do_notify_parent_cldstop(p, CLD_STOPPED);
647 spin_lock(&p->sighand->siglock); 645 spin_lock(&p->sighand->siglock);
648 } 646 }
649 rm_from_queue(SIG_KERNEL_STOP_MASK, &p->signal->shared_pending); 647 rm_from_queue(SIG_KERNEL_STOP_MASK, &p->signal->shared_pending);
@@ -684,7 +682,7 @@ static void handle_stop_signal(int sig, struct task_struct *p)
684 p->signal->flags = SIGNAL_STOP_CONTINUED; 682 p->signal->flags = SIGNAL_STOP_CONTINUED;
685 p->signal->group_exit_code = 0; 683 p->signal->group_exit_code = 0;
686 spin_unlock(&p->sighand->siglock); 684 spin_unlock(&p->sighand->siglock);
687 do_notify_parent_cldstop(p, (p->ptrace & PT_PTRACED), CLD_CONTINUED); 685 do_notify_parent_cldstop(p, CLD_CONTINUED);
688 spin_lock(&p->sighand->siglock); 686 spin_lock(&p->sighand->siglock);
689 } else { 687 } else {
690 /* 688 /*
@@ -1519,14 +1517,14 @@ void do_notify_parent(struct task_struct *tsk, int sig)
1519 spin_unlock_irqrestore(&psig->siglock, flags); 1517 spin_unlock_irqrestore(&psig->siglock, flags);
1520} 1518}
1521 1519
1522static void do_notify_parent_cldstop(struct task_struct *tsk, int to_self, int why) 1520static void do_notify_parent_cldstop(struct task_struct *tsk, int why)
1523{ 1521{
1524 struct siginfo info; 1522 struct siginfo info;
1525 unsigned long flags; 1523 unsigned long flags;
1526 struct task_struct *parent; 1524 struct task_struct *parent;
1527 struct sighand_struct *sighand; 1525 struct sighand_struct *sighand;
1528 1526
1529 if (to_self) 1527 if (tsk->ptrace & PT_PTRACED)
1530 parent = tsk->parent; 1528 parent = tsk->parent;
1531 else { 1529 else {
1532 tsk = tsk->group_leader; 1530 tsk = tsk->group_leader;
@@ -1601,7 +1599,7 @@ static void ptrace_stop(int exit_code, int nostop_code, siginfo_t *info)
1601 !(current->ptrace & PT_ATTACHED)) && 1599 !(current->ptrace & PT_ATTACHED)) &&
1602 (likely(current->parent->signal != current->signal) || 1600 (likely(current->parent->signal != current->signal) ||
1603 !unlikely(current->signal->flags & SIGNAL_GROUP_EXIT))) { 1601 !unlikely(current->signal->flags & SIGNAL_GROUP_EXIT))) {
1604 do_notify_parent_cldstop(current, 1, CLD_TRAPPED); 1602 do_notify_parent_cldstop(current, CLD_TRAPPED);
1605 read_unlock(&tasklist_lock); 1603 read_unlock(&tasklist_lock);
1606 schedule(); 1604 schedule();
1607 } else { 1605 } else {
@@ -1650,25 +1648,17 @@ void ptrace_notify(int exit_code)
1650static void 1648static void
1651finish_stop(int stop_count) 1649finish_stop(int stop_count)
1652{ 1650{
1653 int to_self;
1654
1655 /* 1651 /*
1656 * If there are no other threads in the group, or if there is 1652 * If there are no other threads in the group, or if there is
1657 * a group stop in progress and we are the last to stop, 1653 * a group stop in progress and we are the last to stop,
1658 * report to the parent. When ptraced, every thread reports itself. 1654 * report to the parent. When ptraced, every thread reports itself.
1659 */ 1655 */
1660 if (current->ptrace & PT_PTRACED) 1656 if (stop_count == 0 || (current->ptrace & PT_PTRACED)) {
1661 to_self = 1; 1657 read_lock(&tasklist_lock);
1662 else if (stop_count == 0) 1658 do_notify_parent_cldstop(current, CLD_STOPPED);
1663 to_self = 0; 1659 read_unlock(&tasklist_lock);
1664 else 1660 }
1665 goto out;
1666
1667 read_lock(&tasklist_lock);
1668 do_notify_parent_cldstop(current, to_self, CLD_STOPPED);
1669 read_unlock(&tasklist_lock);
1670 1661
1671out:
1672 schedule(); 1662 schedule();
1673 /* 1663 /*
1674 * Now we don't run again until continued. 1664 * Now we don't run again until continued.