aboutsummaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
authorTejun Heo <tj@kernel.org>2011-06-02 05:14:00 -0400
committerOleg Nesterov <oleg@redhat.com>2011-06-04 12:17:11 -0400
commit6dfca32984237a8a011b5bf367e53341a265b2a4 (patch)
treea879c682f00921959ee28b563b9024c0ac54f861 /kernel
parent3759a0d94c18764247b66511d1038f2b93aa95de (diff)
job control: make task_clear_jobctl_pending() clear TRAPPING automatically
JOBCTL_TRAPPING indicates that ptracer is waiting for tracee to (re)transit into TRACED. task_clear_jobctl_pending() must be called when either tracee enters TRACED or the transition is cancelled for some reason. The former is achieved by explicitly calling task_clear_jobctl_pending() in ptrace_stop() and the latter by calling it at the end of do_signal_stop(). Calling task_clear_jobctl_trapping() at the end of do_signal_stop() limits the scope TRAPPING can be used and is fragile in that seemingly unrelated changes to tracee's control flow can lead to stuck TRAPPING. We already have task_clear_jobctl_pending() calls on those cancelling events to clear JOBCTL_STOP_PENDING. Cancellations can be handled by making those call sites use JOBCTL_PENDING_MASK instead and updating task_clear_jobctl_pending() such that task_clear_jobctl_trapping() is called automatically if no stop/trap is pending. This patch makes the above changes and removes the fallback task_clear_jobctl_trapping() call from do_signal_stop(). Signed-off-by: Tejun Heo <tj@kernel.org> Signed-off-by: Oleg Nesterov <oleg@redhat.com>
Diffstat (limited to 'kernel')
-rw-r--r--kernel/signal.c13
1 files changed, 8 insertions, 5 deletions
diff --git a/kernel/signal.c b/kernel/signal.c
index 288d952fa3b8..637a171b65b6 100644
--- a/kernel/signal.c
+++ b/kernel/signal.c
@@ -253,6 +253,9 @@ static void task_clear_jobctl_trapping(struct task_struct *task)
253 * %JOBCTL_PENDING_MASK. If %JOBCTL_STOP_PENDING is being cleared, other 253 * %JOBCTL_PENDING_MASK. If %JOBCTL_STOP_PENDING is being cleared, other
254 * STOP bits are cleared together. 254 * STOP bits are cleared together.
255 * 255 *
256 * If clearing of @mask leaves no stop or trap pending, this function calls
257 * task_clear_jobctl_trapping().
258 *
256 * CONTEXT: 259 * CONTEXT:
257 * Must be called with @task->sighand->siglock held. 260 * Must be called with @task->sighand->siglock held.
258 */ 261 */
@@ -264,6 +267,9 @@ void task_clear_jobctl_pending(struct task_struct *task, unsigned int mask)
264 mask |= JOBCTL_STOP_CONSUME | JOBCTL_STOP_DEQUEUED; 267 mask |= JOBCTL_STOP_CONSUME | JOBCTL_STOP_DEQUEUED;
265 268
266 task->jobctl &= ~mask; 269 task->jobctl &= ~mask;
270
271 if (!(task->jobctl & JOBCTL_PENDING_MASK))
272 task_clear_jobctl_trapping(task);
267} 273}
268 274
269/** 275/**
@@ -933,7 +939,7 @@ static void complete_signal(int sig, struct task_struct *p, int group)
933 signal->group_stop_count = 0; 939 signal->group_stop_count = 0;
934 t = p; 940 t = p;
935 do { 941 do {
936 task_clear_jobctl_pending(t, JOBCTL_STOP_PENDING); 942 task_clear_jobctl_pending(t, JOBCTL_PENDING_MASK);
937 sigaddset(&t->pending.signal, SIGKILL); 943 sigaddset(&t->pending.signal, SIGKILL);
938 signal_wake_up(t, 1); 944 signal_wake_up(t, 1);
939 } while_each_thread(p, t); 945 } while_each_thread(p, t);
@@ -1168,7 +1174,7 @@ int zap_other_threads(struct task_struct *p)
1168 p->signal->group_stop_count = 0; 1174 p->signal->group_stop_count = 0;
1169 1175
1170 while_each_thread(p, t) { 1176 while_each_thread(p, t) {
1171 task_clear_jobctl_pending(t, JOBCTL_STOP_PENDING); 1177 task_clear_jobctl_pending(t, JOBCTL_PENDING_MASK);
1172 count++; 1178 count++;
1173 1179
1174 /* Don't bother with already dead threads */ 1180 /* Don't bother with already dead threads */
@@ -1964,9 +1970,6 @@ retry:
1964 goto retry; 1970 goto retry;
1965 } 1971 }
1966 1972
1967 /* PTRACE_ATTACH might have raced with task killing, clear trapping */
1968 task_clear_jobctl_trapping(current);
1969
1970 spin_unlock_irq(&current->sighand->siglock); 1973 spin_unlock_irq(&current->sighand->siglock);
1971 1974
1972 tracehook_finish_jctl(); 1975 tracehook_finish_jctl();