diff options
author | Tejun Heo <tj@kernel.org> | 2011-03-23 05:37:00 -0400 |
---|---|---|
committer | Tejun Heo <tj@kernel.org> | 2011-03-23 05:37:00 -0400 |
commit | edf2ed153bcae52de70db00a98b0e81a5668e563 (patch) | |
tree | 78aa0207d78321778d6a504c8138d5bc9ef4b4b4 /kernel | |
parent | 71db5eb99c960e9c30e4b3ed04103c513b6251b5 (diff) |
ptrace: Kill tracehook_notify_jctl()
tracehook_notify_jctl() aids in determining whether and what to report
to the parent when a task is stopped or continued. The function also
adds an extra requirement that siglock may be released across it,
which is currently unused and quite difficult to satisfy in
well-defined manner.
As job control and the notifications are about to receive major
overhaul, remove the tracehook and open code it. If ever necessary,
let's factor it out after the overhaul.
* Oleg spotted incorrect CLD_CONTINUED/STOPPED selection when ptraced.
Fixed.
Signed-off-by: Tejun Heo <tj@kernel.org>
Cc: Oleg Nesterov <oleg@redhat.com>
Cc: Roland McGrath <roland@redhat.com>
Diffstat (limited to 'kernel')
-rw-r--r-- | kernel/signal.c | 34 |
1 files changed, 14 insertions, 20 deletions
diff --git a/kernel/signal.c b/kernel/signal.c index f4db76986ec1..03d874e1058f 100644 --- a/kernel/signal.c +++ b/kernel/signal.c | |||
@@ -1727,7 +1727,7 @@ void ptrace_notify(int exit_code) | |||
1727 | static int do_signal_stop(int signr) | 1727 | static int do_signal_stop(int signr) |
1728 | { | 1728 | { |
1729 | struct signal_struct *sig = current->signal; | 1729 | struct signal_struct *sig = current->signal; |
1730 | int notify; | 1730 | int notify = 0; |
1731 | 1731 | ||
1732 | if (!sig->group_stop_count) { | 1732 | if (!sig->group_stop_count) { |
1733 | struct task_struct *t; | 1733 | struct task_struct *t; |
@@ -1759,19 +1759,16 @@ static int do_signal_stop(int signr) | |||
1759 | * a group stop in progress and we are the last to stop, report | 1759 | * a group stop in progress and we are the last to stop, report |
1760 | * to the parent. When ptraced, every thread reports itself. | 1760 | * to the parent. When ptraced, every thread reports itself. |
1761 | */ | 1761 | */ |
1762 | notify = sig->group_stop_count == 1 ? CLD_STOPPED : 0; | 1762 | if (!--sig->group_stop_count) { |
1763 | notify = tracehook_notify_jctl(notify, CLD_STOPPED); | 1763 | sig->flags = SIGNAL_STOP_STOPPED; |
1764 | /* | 1764 | notify = CLD_STOPPED; |
1765 | * tracehook_notify_jctl() can drop and reacquire siglock, so | ||
1766 | * we keep ->group_stop_count != 0 before the call. If SIGCONT | ||
1767 | * or SIGKILL comes in between ->group_stop_count == 0. | ||
1768 | */ | ||
1769 | if (sig->group_stop_count) { | ||
1770 | if (!--sig->group_stop_count) | ||
1771 | sig->flags = SIGNAL_STOP_STOPPED; | ||
1772 | current->exit_code = sig->group_exit_code; | ||
1773 | __set_current_state(TASK_STOPPED); | ||
1774 | } | 1765 | } |
1766 | if (task_ptrace(current)) | ||
1767 | notify = CLD_STOPPED; | ||
1768 | |||
1769 | current->exit_code = sig->group_exit_code; | ||
1770 | __set_current_state(TASK_STOPPED); | ||
1771 | |||
1775 | spin_unlock_irq(¤t->sighand->siglock); | 1772 | spin_unlock_irq(¤t->sighand->siglock); |
1776 | 1773 | ||
1777 | if (notify) { | 1774 | if (notify) { |
@@ -1860,14 +1857,11 @@ relock: | |||
1860 | 1857 | ||
1861 | signal->flags &= ~SIGNAL_CLD_MASK; | 1858 | signal->flags &= ~SIGNAL_CLD_MASK; |
1862 | 1859 | ||
1863 | why = tracehook_notify_jctl(why, CLD_CONTINUED); | ||
1864 | spin_unlock_irq(&sighand->siglock); | 1860 | spin_unlock_irq(&sighand->siglock); |
1865 | 1861 | ||
1866 | if (why) { | 1862 | read_lock(&tasklist_lock); |
1867 | read_lock(&tasklist_lock); | 1863 | do_notify_parent_cldstop(current->group_leader, why); |
1868 | do_notify_parent_cldstop(current->group_leader, why); | 1864 | read_unlock(&tasklist_lock); |
1869 | read_unlock(&tasklist_lock); | ||
1870 | } | ||
1871 | goto relock; | 1865 | goto relock; |
1872 | } | 1866 | } |
1873 | 1867 | ||
@@ -2034,7 +2028,7 @@ void exit_signals(struct task_struct *tsk) | |||
2034 | if (unlikely(tsk->signal->group_stop_count) && | 2028 | if (unlikely(tsk->signal->group_stop_count) && |
2035 | !--tsk->signal->group_stop_count) { | 2029 | !--tsk->signal->group_stop_count) { |
2036 | tsk->signal->flags = SIGNAL_STOP_STOPPED; | 2030 | tsk->signal->flags = SIGNAL_STOP_STOPPED; |
2037 | group_stop = tracehook_notify_jctl(CLD_STOPPED, CLD_STOPPED); | 2031 | group_stop = CLD_STOPPED; |
2038 | } | 2032 | } |
2039 | out: | 2033 | out: |
2040 | spin_unlock_irq(&tsk->sighand->siglock); | 2034 | spin_unlock_irq(&tsk->sighand->siglock); |