aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTejun Heo <tj@kernel.org>2011-03-23 05:37:00 -0400
committerTejun Heo <tj@kernel.org>2011-03-23 05:37:00 -0400
commitedf2ed153bcae52de70db00a98b0e81a5668e563 (patch)
tree78aa0207d78321778d6a504c8138d5bc9ef4b4b4
parent71db5eb99c960e9c30e4b3ed04103c513b6251b5 (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>
-rw-r--r--include/linux/tracehook.h27
-rw-r--r--kernel/signal.c34
2 files changed, 14 insertions, 47 deletions
diff --git a/include/linux/tracehook.h b/include/linux/tracehook.h
index 3a2e66d88a3..b073f3c8adc 100644
--- a/include/linux/tracehook.h
+++ b/include/linux/tracehook.h
@@ -469,33 +469,6 @@ static inline int tracehook_get_signal(struct task_struct *task,
469} 469}
470 470
471/** 471/**
472 * tracehook_notify_jctl - report about job control stop/continue
473 * @notify: zero, %CLD_STOPPED or %CLD_CONTINUED
474 * @why: %CLD_STOPPED or %CLD_CONTINUED
475 *
476 * This is called when we might call do_notify_parent_cldstop().
477 *
478 * @notify is zero if we would not ordinarily send a %SIGCHLD,
479 * or is the %CLD_STOPPED or %CLD_CONTINUED .si_code for %SIGCHLD.
480 *
481 * @why is %CLD_STOPPED when about to stop for job control;
482 * we are already in %TASK_STOPPED state, about to call schedule().
483 * It might also be that we have just exited (check %PF_EXITING),
484 * but need to report that a group-wide stop is complete.
485 *
486 * @why is %CLD_CONTINUED when waking up after job control stop and
487 * ready to make a delayed @notify report.
488 *
489 * Return the %CLD_* value for %SIGCHLD, or zero to generate no signal.
490 *
491 * Called with the siglock held.
492 */
493static inline int tracehook_notify_jctl(int notify, int why)
494{
495 return notify ?: (current->ptrace & PT_PTRACED) ? why : 0;
496}
497
498/**
499 * tracehook_finish_jctl - report about return from job control stop 472 * tracehook_finish_jctl - report about return from job control stop
500 * 473 *
501 * This is called by do_signal_stop() after wakeup. 474 * This is called by do_signal_stop() after wakeup.
diff --git a/kernel/signal.c b/kernel/signal.c
index f4db76986ec..03d874e1058 100644
--- a/kernel/signal.c
+++ b/kernel/signal.c
@@ -1727,7 +1727,7 @@ void ptrace_notify(int exit_code)
1727static int do_signal_stop(int signr) 1727static 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(&current->sighand->siglock); 1772 spin_unlock_irq(&current->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 }
2039out: 2033out:
2040 spin_unlock_irq(&tsk->sighand->siglock); 2034 spin_unlock_irq(&tsk->sighand->siglock);