aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/ptrace.c
diff options
context:
space:
mode:
authorTejun Heo <tj@kernel.org>2011-06-14 05:20:14 -0400
committerOleg Nesterov <oleg@redhat.com>2011-06-16 15:41:52 -0400
commit73ddff2bee159ffb580bd24faf625cd5e628f5ec (patch)
tree218cf5101b67c98ef99814e59706976d3ad245c2 /kernel/ptrace.c
parentdd1d6772692316fe35094085c5e4d9a370ad3462 (diff)
job control: introduce JOBCTL_TRAP_STOP and use it for group stop trap
do_signal_stop() implemented both normal group stop and trap for group stop while ptraced. This approach has been enough but scheduled changes require trap mechanism which can be used in more generic manner and using group stop trap for generic trap site simplifies both userland visible interface and implementation. This patch adds a new jobctl flag - JOBCTL_TRAP_STOP. When set, it triggers a trap site, which behaves like group stop trap, in get_signal_to_deliver() after checking for pending signals. While ptraced, do_signal_stop() doesn't stop itself. It initiates group stop if requested and schedules JOBCTL_TRAP_STOP and returns. The caller - get_signal_to_deliver() - is responsible for checking whether TRAP_STOP is pending afterwards and handling it. ptrace_attach() is updated to use JOBCTL_TRAP_STOP instead of JOBCTL_STOP_PENDING and __ptrace_unlink() to clear all pending trap bits and TRAPPING so that TRAP_STOP and future trap bits don't linger after detach. While at it, add proper function comment to do_signal_stop() and make it return bool. -v2: __ptrace_unlink() updated to clear JOBCTL_TRAP_MASK and TRAPPING instead of JOBCTL_PENDING_MASK. This avoids accidentally clearing JOBCTL_STOP_CONSUME. Spotted by Oleg. -v3: do_signal_stop() updated to return %false without dropping siglock while ptraced and TRAP_STOP check moved inside for(;;) loop after group stop participation. This avoids unnecessary relocking and also will help avoiding unnecessary traps by consuming group stop before handling pending traps. -v4: Jobctl trap handling moved into a separate function - do_jobctl_trap(). Signed-off-by: Tejun Heo <tj@kernel.org> Cc: Oleg Nesterov <oleg@redhat.com>
Diffstat (limited to 'kernel/ptrace.c')
-rw-r--r--kernel/ptrace.c12
1 files changed, 9 insertions, 3 deletions
diff --git a/kernel/ptrace.c b/kernel/ptrace.c
index 7f05f3a1267b..45a8a4c5d8b2 100644
--- a/kernel/ptrace.c
+++ b/kernel/ptrace.c
@@ -83,6 +83,13 @@ void __ptrace_unlink(struct task_struct *child)
83 spin_lock(&child->sighand->siglock); 83 spin_lock(&child->sighand->siglock);
84 84
85 /* 85 /*
86 * Clear all pending traps and TRAPPING. TRAPPING should be
87 * cleared regardless of JOBCTL_STOP_PENDING. Do it explicitly.
88 */
89 task_clear_jobctl_pending(child, JOBCTL_TRAP_MASK);
90 task_clear_jobctl_trapping(child);
91
92 /*
86 * Reinstate JOBCTL_STOP_PENDING if group stop is in effect and 93 * Reinstate JOBCTL_STOP_PENDING if group stop is in effect and
87 * @child isn't dead. 94 * @child isn't dead.
88 */ 95 */
@@ -246,7 +253,7 @@ static int ptrace_attach(struct task_struct *task)
246 spin_lock(&task->sighand->siglock); 253 spin_lock(&task->sighand->siglock);
247 254
248 /* 255 /*
249 * If the task is already STOPPED, set JOBCTL_STOP_PENDING and 256 * If the task is already STOPPED, set JOBCTL_TRAP_STOP and
250 * TRAPPING, and kick it so that it transits to TRACED. TRAPPING 257 * TRAPPING, and kick it so that it transits to TRACED. TRAPPING
251 * will be cleared if the child completes the transition or any 258 * will be cleared if the child completes the transition or any
252 * event which clears the group stop states happens. We'll wait 259 * event which clears the group stop states happens. We'll wait
@@ -263,8 +270,7 @@ static int ptrace_attach(struct task_struct *task)
263 * in and out of STOPPED are protected by siglock. 270 * in and out of STOPPED are protected by siglock.
264 */ 271 */
265 if (task_is_stopped(task) && 272 if (task_is_stopped(task) &&
266 task_set_jobctl_pending(task, 273 task_set_jobctl_pending(task, JOBCTL_TRAP_STOP | JOBCTL_TRAPPING))
267 JOBCTL_STOP_PENDING | JOBCTL_TRAPPING))
268 signal_wake_up(task, 1); 274 signal_wake_up(task, 1);
269 275
270 spin_unlock(&task->sighand->siglock); 276 spin_unlock(&task->sighand->siglock);